• 10 hours
  • Medium

Free online content available in this course.

course.header.alt.is_video

course.header.alt.is_certifying

Got it!

Last updated on 4/2/20

Manipulate data in a series of requests

Now that we have a little more experience with HTTP requests let's look in more depth at using promises and async/await to make multiple requests, both in parallel and in series.

A blog about cats

In this chapter, you are going to create a random blog post generator, using an API created for this course. Your app will make three parallel GET calls, followed by a final POST call. This should show you the real value of async/await.

Practice!

Head to CodePen Exercise P3CH3a and follow the instructions below.

Seeing as we will be making four HTTP requests, it would be far better to make one function that we can call four times, rather than to write out very similar code four times. Let's build our makeRequest() function.

  1. Create a new function called makeRequest() which accepts a verb, a URL and a data object as arguments and returns a Promise.

  2. Create an XMLHttpRequest object called request, and call its open() method, passing the verb and url arguments from the overall function call.

  3. Implement our request's onreadystatechange function. Status codes 200 and 201 are success codes, anything else is an error — remember, this only matters for a ready state of 4. For a successful request, the Promise will resolve with the response as an object. For an unsuccessful one, it will reject with the response as an object.

  4.  If the request type is 'POST', set the request's Content-Type header to application/json and send the request with the stringified data object. Otherwise, simply send the request. 

  5. Check your makeRequest() function with the screencast.

Once you've given it a go, watch me code a solution and see how your approach compares:

Now let's use async/await to put everything together.

Practice!

Head to CodePen Exercise P3CH3b and follow the instructions below.

Let's build an async function to make the requests we need and print the final result to the DOM.

We could make and await each request, one after the other. However, this method isn't very performant, as the overall time will be far longer. Instead, we are going to use Promise.all, a method which allows Promises to run in parallel and which resolves when all of the Promises we pass it have resolved. 

  1. Create an async function called createPost(). Here are the API endpoints we will be needing:

    • GET /generate-uid — returns { uid: string }

    • GET /generate-title — returns { title: string }

    • GET /generate-lorem — returns { lorem: string }

    • POST /create-post-with-uid

      • requires { uid: string, title: string, content: string }

      • returns { message: string, post: { id: string, title: string, content: string } }

  2. Create three Promises — uidPromisetitlePromise and contentPromise — using the makeRequest() function and passing it the 'GET' verb and the appropriate URLs.

  3. The Promise.all method takes an array of Promises as an argument, and returns an array containing the resolved values of each Promise. We could do this:

    const responses = await Promise.all([uidPromise, titlePromise, contentPromise]);

    However, that would give us a responses array, leading to less readable code (what exactly is responses[2]?). Instead, we'll use destructuring syntax. Add the following line:

    const [uidResponse, titleResponse, contentResponse] = await Promise.all([uidPromise, titlePromise, contentPromise]);

    This creates separate named constants for each resolved Promise whilst still leveraging Promise.all. Pretty awesome, right?

  4. Now we need to collate the various responses to create our final POST request. Don't forget: each resolved Promise currently contains the object returned by the server, not just the text. Looking back at the API docs, create a Promise called postPromise using makeRequest(), passing the verb POST, the correct URL, and the required kind of data object, containing the data extracted from the previous three requests.

  5. Now, using await, create a constant called post to hold the POST request's response data.

  6. Finally, extract the blog post data from post and display it in the DOM, in the text content of postTitlepostId and postContent.

  7. Now all we need to do is hook up our button! Add a click event listener to our Generate Post button and use it to call createPost(). Hit Show result, click the Generate Post button and see what happens!

Once you've given it a go, watch me code a solution and see how your approach compares:

Let's recap!

In this chapter, we looked at how to use async/await to handle parallel and serial HTTP requests. We looked at how  Promise.all , along with destructuring syntax, is a powerful tool for leveraging multiple simultaneous AJAX requests.

What we did not do correctly, however, is error handling. We have a reject() call in our promise, but no way of handling any errors returned by the server. There are also other potential bugs because we have not really thought about what could go wrong.

Not to worry though: the next chapter looks in a bit more detail at error handling.

Example of certificate of achievement
Example of certificate of achievement