Parsing User JSON - ldco2016/microurb_web_framework GitHub Wiki
import { User } from "./User";
import { Eventing } from "./Eventing";
export class Collection {
models: User[] = [];
events: Eventing = new Eventing();
get on() {
return this.events.on;
}
get trigger() {
return this.events.trigger;
}
}
I am going to ensure that my class Collection
has a fetch()
method that will make a request to /users
and retrieve all the different users that I have:
I first implemented this with Axios just so I could see what information I was going to get back from JSON Server. I needed to parse this stuff and turn each object that I get back into an instance of a user. To do so, inside the index.ts
file I completed the following:
import axios from "axios";
axios.get("http://localhost:3000/users");
I then chained on a .then()
statement that got called with some response
object that is of type AxiosResponse
like so:
import axios, { AxiosResponse } from "axios";
axios.get("http://localhost:3000/users").then((response: AxiosResponse) => {
console.log(response.data);
});
So you can see that when I make a network request over to that endpoint, I get back an array of objects and each object is going to have an id a name and an age.
So the object i get back essentially conforms to my UserProps
interface. So I want to take objects that conform to that interface and use them to create different instances of users. So I just need to loop over the response, take each one of these objects and throw them into buildUser
.
Back in my Collection.ts
file, I now need to use Axios and probably make reference to the UserProps
interface inside of here:
import axios from "axios";
import { User, UserProps } from "./User";
import { Eventing } from "./Eventing";
export class Collection {
models: User[] = [];
events: Eventing = new Eventing();
get on() {
return this.events.on;
}
get trigger() {
return this.events.trigger;
}
fetch(): void {
axios.get();
}
}
The argument to get()
is going to be the url that I want to make my request to. I could hardcode it in, but I will eventually have to dynamically specify that root url on the fly. So whenever we create an instance of class Collection
I should have to pass in the root url that I want to make this request to and then I can reuse it for other types of records as well. So I will add in a constructor()
and use the shortened syntax to receive a public
variable called rootUrl
with type of string
like so:
import axios from "axios";
import { User, UserProps } from "./User";
import { Eventing } from "./Eventing";
export class Collection {
models: User[] = [];
events: Eventing = new Eventing();
constructor(public rootUrl: string) {}
get on() {
return this.events.on;
}
get trigger() {
return this.events.trigger;
}
fetch(): void {
axios.get(this.rootUrl);
}
}
And then I was able to reference that rootUrl
inside the fetch()
method axios request with this.rootUrl
.
So now I can chain on a .then()
statement, receive all that JSON data and turn each of those objects into an instance of a user like so:
import axios, { AxiosResponse } from "axios";
import { User, UserProps } from "./User";
import { Eventing } from "./Eventing";
export class Collection {
models: User[] = [];
events: Eventing = new Eventing();
constructor(public rootUrl: string) {}
get on() {
return this.events.on;
}
get trigger() {
return this.events.trigger;
}
fetch(): void {
axios.get(this.rootUrl).then((response: AxiosResponse) => {});
}
}
Then I have a response.data
property inside that .then()
statement and I want to run a loop over response.data
because that is going to be the array of records that we get back from the JSON Server. I will do a forEach()
on this thing and for every object inside there I will turn it into an instance of a user and add it to the models array like so:
import axios, { AxiosResponse } from "axios";
import { User, UserProps } from "./User";
import { Eventing } from "./Eventing";
export class Collection {
models: User[] = [];
events: Eventing = new Eventing();
constructor(public rootUrl: string) {}
get on() {
return this.events.on;
}
get trigger() {
return this.events.trigger;
}
fetch(): void {
axios.get(this.rootUrl).then((response: AxiosResponse) => {
response.data.forEach((value: UserProps) => {});
});
}
}
So I will take the value
and stick into User.buildUser()
which will create a user and then push it into the models array as mentioned above like so:
import axios, { AxiosResponse } from "axios";
import { User, UserProps } from "./User";
import { Eventing } from "./Eventing";
export class Collection {
models: User[] = [];
events: Eventing = new Eventing();
constructor(public rootUrl: string) {}
get on() {
return this.events.on;
}
get trigger() {
return this.events.trigger;
}
fetch(): void {
axios.get(this.rootUrl).then((response: AxiosResponse) => {
response.data.forEach((value: UserProps) => {
const user = User.buildUser(value);
this.models.push(user);
});
});
}
}
Now I can test this out easily inside of index.ts
like so:
import { Collection } from "./models/Collection";
I will create a new instance of a Collection
like so:
import { Collection } from "./models/Collection";
const collection = new Collection("http://localhost:3000/users");
collection.fetch();
IMPORTANT NOTE:
Right now I am not returning a Promise from collection.fetch()
. I am going to rely upon the Eventing system to know whether or not an event has changed.
So after running the entire forEach()
I will trigger a change event like so:
import axios, { AxiosResponse } from "axios";
import { User, UserProps } from "./User";
import { Eventing } from "./Eventing";
export class Collection {
models: User[] = [];
events: Eventing = new Eventing();
constructor(public rootUrl: string) {}
get on() {
return this.events.on;
}
get trigger() {
return this.events.trigger;
}
fetch(): void {
axios.get(this.rootUrl).then((response: AxiosResponse) => {
response.data.forEach((value: UserProps) => {
const user = User.buildUser(value);
this.models.push(user);
});
this.trigger("change");
});
}
}
Then back inside of index.ts
, to get a notification of when this has been completed, I can add on an event handler like so:
import { Collection } from "./models/Collection";
const collection = new Collection("http://localhost:3000/users");
collection.on("change", () => {
console.log(collection);
});
collection.fetch();
I console logged the entire collection and headed to the browser.
I should be able to expand it, open up models and see all those different users:
The users that I see in here are all the users reflected in my users.db
file. The only problem now is that my users collection only works with users:
export class Collection {
models: User[] = [];
events: Eventing = new Eventing();
...
So I am going to have to turn this into a generic class to make it reusable.