Create an Angular service to get your HTTP data by converting an observable into a promise and using async await to handle the response.
- [Instructor] We will be sending a request for our messages to our newly created web service. So, the first thing we need to do is create a service in Angular. We could put the HTTP request directly in our component, but let's try to keep our structure nice and separate concerns. Let our components deal with UI and let our services deal with providing services to those components. Let's begin by creating a new file in our app directory. We can call this web.service.ts and now we can create the class with the same name and export it.
Then I'll make a new function called, "Get Messages," which will return the messages once we get them with an http call. So we will need access to the angular http service. So let's import that in from angular/http. To use http, we will need to have it injected into the class constructor, so next, above our GetMessage function, let's create a constructor.
And let's inject an http. This will also save a local reference, which we will then access inside our GetMessages function. Angular will know to inject an instance of the http service because we specified the type with TypeScript, as shown on line five. We can now access this through this.http, as we will see inside our function. And from that, we can call .get.
The first parameter we'll need to specify is the URL. In this case, it will be the location that Visual Studio launches our server into, so let's give that a try. And we can grab that from the browser. And then we can paste that in as the first parameter. By default, http.get returns an observable, and we'll cover those in later chapters, but for now, I'll convert this to a promise, so it might be something we are more familiar with, since previous versions of Angular used promises.
I also do this because I would like to use the async/await functionality inside my component, which we will see shortly. In order to use toPromise, which will convert our current observable into a promise, we will need to import that functionality from a library called RxJS. RxJS is a library we will also be looking at in more detail later in this course. Let's go to the top of our file and import that. I'll import it from the following location: RxJS/add/operator/toPromise.
Now at the end of our observable, we can type in .toPromise. And finally, let's return our new promise. In order to use our service and the component such as in our message component, we will need to register it with our main module, so let's open up app.module.ts, and first, we'll import it.
Just like our components register inside the declarations list, we will need to create another list for services called "Providers." Then we'll pass in our web service. We will also need to add the http module to our app module, so below our last import, let's do that.
And then let's add it to our imports list. So I'll copy httpmodule and place it inside our imports list. If we try to save the changes and view our app in our browser, we will see it's not working. The reason is because Angular does not know that this is a service. It's just a plain class at the moment. Just like we decorated a component with Component, we need to decorate our web service with the service decorator. For services, the decorator will be called Injectable, and first, we need to import that in from @angular/core.
And then we can decorate our class. Unlike our component decorator, we don't need to specify any parameters. Next, let's make sure there are no more errors inside the browser, and now let's import our new service into our component. Then let's inject it into the constructor, just like we did with the http service inside our web service. So let's create our constructor.
And we will inject our web service. Now that we have access to our service, where should we make the call to get our data? If we do it in the constructor, it could delay our app and component initialization until the data comes in, so it's best not to do anything too expensive or costly in the constructor. Instead, we can use a function called "ng on init," which gets called once the component is done initializing and after the constructor gets called.
Let's set that up and call our web service, .getmessages, inside it. If we save this and show it in our browser, we should see an error about access control allow origin. This means that we need to enable CORS, or Cross Origin Resource Sharing, on our back end in order to have requests from a different URL work.
And since our port is different, this is considered a different URL. Let's make that change now on our back end. So let's go to our back end project. Let's add a CORS middleware. So after line eight, I'll add a new line, and then I'll add app.use, and I'll pass in an error function that takes in a request, a response, and next. Inside here, we'll make a call to response dot header, and for the first parameter, we'll pass in Access-Control-Allow-Origin with dashes in between, and for the second parameter, I'll supply an asterisk, indicating we will allow any type of location or URL.
Next I'll copy this line and paste it below, and I'll modify Access-Control-Allow-Origin to Access-Control-Allow-Headers. Then, for the second parameter, I'll supply several different header types, such as Origin, X-Requested-With, Content-Type, and Accept.
Then let's call next on the last line. That way we'll let Express know we're finished with this middleware. If we save the changes, we can see nodemon has automatically restarted our server. And the last thing we need to do is make sure that our middleware is above our route. So, let's move everything between lines nine and 13 above our app.get on line six. And I'll add a couple spaces. Now let's say that, and if we take a look at our angular app if we go back to our web app and refresh, we should see there's no longer any error.
And if we go to our network tab, scroll down to the messages request, we can see that the response did come through with our list. Next, let's go back to Visual Studio Code. We're calling GetMessages and we are getting the messages response, but we aren't doing anything with it yet. I will use asynch and await to access the response. So let's set the return value to a response variable, and then console.log the response.
If we tried this now, it would not work, because it would just try to console.log the promise, not the response, since inside web service, we are returning a promise. And so what we need to do is wait for the response to come in through the promise. Let's do that by adding await in front of our GetMessages call, so on line 19, I'll add in await. And to use await inside a function, that function must be designated async. So let's append that to ngOnInit.
Let's try to output the list directly instead of the response. Let's go back to Visual Studio Code. We can access the body by typing "text," but since it's json, we will then need to parse it if we want to access properties inside that json, such as the owner or the text. So to skip that json parsing step, instead of .txt, we can use .json. Let's give that a try.
And we can see it's coming in as a json array with our json message objects inside. Let's go back to Visual Studio Code. At this point, we can set this.messages to response.json and replace the message definition from the class with an empty list, which will show that we must be displaying our message list from the back end, since it's no longer defined locally. So I'll replace this console log with this.messages and set that to response.json.
Now let's give this a try. We can see we're getting the messages from our back end since they differ from the ones in our front end. Let's go ahead and empty this list. Now that we know how to serve and display data from the back end, let's next look at saving new data.
- Setting up the infrastructure
- Displaying data in Angular 2
- Refining your layout with Angular Material
- Getting your data from Node.js
- Saving data to a list
- Creating the component
- Getting your input data
- Creating reactive forms in Angular
- Creating a security middleware
Skill Level Intermediate
Q: This course was updated on 10/17/2017. What changed?
A: We updated five videos to reflect changes to the setup and data retrieval and display processes in Angular 2. For example, instead of using a Git Angular template, the updated course uses the Angular CLI to generate a starting template, for a smooth runtime experience.