Promise object and the
Promise.prototype.then() method. We’re gonna look at how to make an HTTP request using the Fetch API and how to asynchronously process the response in a promise chain.
In addition, we'll discuss the three mutually exclusive states a promise can be in: pending, fulfilled, or rejected.
Instructor: [00:00] In this lesson, I want to show you how to use promises and the Fetch API to load a list of Star Wars films from the Star Wars API. Before we start coding, let's take a look what the API returns. When we access the /films endpoint, we get back an array of six items.
[00:18] Each film has several properties. For example, the title and the episode ID which is where we're going to be using. We're going to start by making a fetch request to the API URL and more specifically the films endpoint.
[00:34] Now, making an HTTP request as an asynchronous operation, so fetch doesn't return our data directly, what it returns is a response promise. I'm going to take that promise and store it in a variable. A promise is a placeholder for the eventual result of an asynchronous operation.
[00:52] In this case, the promise represents the HTTP response that we're going to get back eventually. In this way, a promise is similar to a Pizza Bazaar. You'd get a restaurant when you order a Pizza. You don't get the Pizza right away. What you get is a promise that say 10 minutes time you'll get a Pizza, and the Bazaar tells you when that is ready.
[01:13] Let's now log our response promise to the console just so we can see what it currently looks like. Head over to the browser, open the DevTools, give this a refresh, and we can see that we have a pending promise.
[01:28] Let's take a quick detour and talk about this three possible states that a promise can be in. Before the result is ready, the promise is pending. If the result becomes available, the promise is fulfilled. If however an error happened, the promise is rejected.
[01:46] Once the promise is no longer pending, that is, if it has been fulfilled or rejected, we say that the promise has been settled. Once a promise has been settled, it can no longer change its state. That is, if a promise transitions to the fulfilled or rejected state, it stays in that state forever.
[02:05] OK, let's go back to our example and let's see how we can use the response promise. We'll call the promises.then method, and what we'll do is we'll attach a callback that is called once the promise has been fulfilled.
[02:19] In this case, we want to start by saying console.log response, so that we can see what we actually get. Let's head over to the browser, hit refresh. You can see that we now have a response. We can see various properties. For example, the response status code was 200, which means that the OK flag is set to true.
[02:42] What we want to do now is we want to read the body of the responses JSON. We're going to call the response.json method. The JSON method reads the full body of the response and parses the text as JSON. This is another asynchronous operation which is where the JSON method returns a promise itself.
[03:02] What we're going to do now is we're going to return that promise from our full_filament handler. This means, we can now create what is called a promise chain by tacking on another then call to the end. Here, we're going to specify another full_filament handler.
[03:16] That one is going to receive the actual films as the value. Whatever value we return from the first full_filament handler is going to be passed as a parameter to the second one.
[03:25] This is why it's called a promise chain. That makes sure all of this is working properly. We'll say consle.log films.link, and we'd expect this to be six as we saw before. Give this a save and refresh the browser page.
[03:43] Yep. There we go. We get back six. In a typical application, you'll usually want to transform the data that you got back from the API. Here, we want to display the episode numbers and the titles of all films.
[03:57] We're going to go ahead and we're going to map over the films. We're going to say films.map, and we want to map each film to its episode ID. We also want to show the film's title. The results of that we want to join together with a new line.
[04:19] Instead of logging the film titles to the console, let's quickly take a look at our HTML file. We'll see that we have a div with an ID of output. What I'm going to do is I'm going to grab that div by saying const output equals document getElementById output.
[04:37] We want to set that elements innerText to our film titles. Head over to the browser, close the DevTools, hit refresh, and here we go. We have a list of Star Wars film titles. As you can see, the API doesn't return the films in the correct order.
[04:55] What we want to do is, we're going to use the sort method, going to pass it A and B, and we're going to sort the films by their episode ID and that should fix our sorting problem.
[05:09] There is one thing I want to fix. If we reload the page, you'll see that our div says empty in the beginning. We don't display anything until our data comes back from the API. What I'm going to do is, I'm going to move our output up here, and before we make our fetch call, I'm going to say, output.innerText equals loading.
[05:29] Now if we refresh the page, we'll see that were loading, and when the data is there, we're going to replace the content. Much better. Lastly, I want to simplify our code a little bit. Our first full_filament handler does nothing, but returning response.json.
[05:46] We can simplify the error function. Let's get rid of the curly braces and the return statement. Also, we don't really need the response promise variable, since we're just using it once. I'm going to get rid of this one. We're just going to say fetch and attach the then handlers.
[06:05] We're also going to create a separate function for trading our film titles. We're going to say getFilmTiltes except the films, and we can move this entire section into the separate function. This way, our full_filament handler stay little bit cleaner.
[06:24] Let's make sure everything still works. Here you go. This is how you use promises and the Fetch API.
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://starwars.egghead.training/films. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing)
Current start wars API is no longer working :/
@Carlos: Apologies for the inconveniences. The API should be back up and running!
Thumbs up. Great job.