loading...

JavaScript Fetch API and using Async/Await

shoupn profile image Nick Shoup ・3 min read

This post was originally published on my blog Fundamentals of Code

Fetch It

If you've been using JavaScript for a while, you've probably used the ES6 fetch API, I actually covered it somewhat in my previous post where I decided to refactor a bit of code, that was using the GitHub API to return user information. It was a fun post and a little bit of work, and I actually learned a little bit more about using the fetch API myself. Especially as it relates to async JavaScript methods.

A Little Bit About Fetch

Using fetch() can be thought of as using a lower level API for performing your needs to return a response from a URI, in other words sans framework or library. fetch was introduced so that developers could more easily make requests to URI's or rest endpoints for applications. Before this the standard was to use ajax calls to using the something the XMLHttpRequest like so var xhr = new XMLHttpRequest;. It's not bad, and still exists in a lot of legacy code out there, so you should also have an understanding of how this works, and the origins of XMLHttpRequests, as this was the standard before REST came to the scene.

The Promise Code

The below code is not bad, and it does function correctly, however, there are a couple of things about it that make it a little cringe-worthy. Notice the .then() function, which supports a callback function for resolving the fetch function. As I said this functions and is fairly readable. In the few short lines of code that it is. However, there are the chaining of .then()'s and this can lead into what is often referred to as callback hell, or nested callbacks, that quickly reduce readability and can easily lead to bad performance or bugs.

function getUser(name){
 fetch(`https://api.github.com/users/${name}`)
  .then(function(response) {
    return response.json();
  })
  .then(function(json) {
    console.log(json);
  });
};

//get user data
getUser('yourUsernameHere');

Async And Await to the Rescue

Using Async/Await is not fully supported across all browsers, so you should be aware of this, and check your needs when developing. Here is a resource for checking browser support and functionality, and check here for using fetch. These keywords didn't all make it into the initial ES6 implementation of JavaScript but expect this to be more widely supported across browsers. In my opinion and experience, the below code allows for much easier readability. Keep in mind that in order to call a function using the await keyword, it must be within the async function as in the below example. This is just the syntactical sugar of making things more readable, in turn handling the return of a Promise object more seamlessly and feels more like a synchronous function call rather than asynchronously handled.

async function getUserAsync(name) 
{
  let response = await fetch(`https://api.github.com/users/${name}`);
  let data = await response.json()
  return data;
}

getUserAsync('yourUsernameHere')
  .then(data => console.log(data)); 

There's a lot that can be covered in this topic, but I thought this was a nice explanation of using these newer features and what to expect in the future as they become more widely supported. I know professionally I still have to support IE 11, but don't let something like that hold you back from using these newer features of the evolving JavaScript language. It really is a beautiful thing to behold.

Posted on by:

shoupn profile

Nick Shoup

@shoupn

GIS Developer, outdoor enthusiast, cryptocurrency/blockchain enthusiast, father, and husband. I really just want to share my passion for coding with others.

Discussion

markdown guide
 

I just signed up to Dev Community for one reason, to tell you that this is the shortest and most helpful article I've ever read on async\await.

You cut right to the chase, you used fetch (instead of setTimeOut), and you wrote a single, simple, readable function. Beautiful. Please keep it up.

 
 

An alternative solution for getUserAsync using then:

async function getUserAsync(name) 
{
  await fetch(`https://api.github.com/users/${name}`).then(async (response)=> {
  return await response.json()
}

Agree with you that your solution is more readable.
Actually, does it make sense to use async/await inside then?

(I'm getting back to javascript after a few years and this Promise handling is new for me)

 

Actually, I think your implementation is a bit neater, as it keeps the async and await handling inside the function. Nice!

 

That won't work, but this is a good way to keep things brief with fetch, and doesn't require the extraneous res variable:

const data = await fetch(`https://api.github.com/users/${name}`).then(r => r.json());
 

Seems like too many async/await for me but I'm not sure which one can be removed right now.
At least last await is redundant: jakearchibald.com/2017/await-vs-re...

 
 

ya that was my question... doesn't look like there is any error handling. my guess is that the implementation is stripped down as much as possible to communicate the concept, and shouldn't be referenced as a production example...

but i'm not sure about that.

 

You can use a try-catch block to handle errors. Works similar to .catch when using .then

async function getUserAsync(name) {
  try{
    let response = await fetch(`https://api.github.com/users/${name}`);
    return await response.json();
  }catch(err){
    console.error(err);
    // Handle errors here
  }
}

yep for sure... this is a great example. Thanks!

Accurate, however if you are using the

.then()

method, then you can also use the

.catch()

and the

.finally()

methods as well!

 

"The Promise returned from fetch() won’t reject on HTTP error status even if the response is an HTTP 404 or 500. Instead, it will resolve normally (with ok status set to false), and it will only reject on network failure or if anything prevented the request from completing."

That said you can handle the errors

  1. from the response
  2. from the data returned outside the function.

ya i know... the spec is pretty clear, but it's not handled in the implementation in the article. that's all... so my assumption is that you'd need a bit of a rework to include that handling in order to really build something production-ready with async / await

 

I don't know if this is a good practice, but I do this

const getData = (url) => {
  const res = await fetch(url)
  const data = await res.json()
  return data
}

// MAIN METHOD
(async () => {
// Make all your API calls here with async/await with 0 then
const user = await getData("https://idk.test/user/1")
const notes = await getData("https://idk.test/notes")
})()



Is this good?

 

I do it this way.. It works without async/await lol
I read the article and i still haven't understood, is it an obligatory to use async/await?
why they should be used? When we should use them?

function getUser(name){
fetch(https://api.github.com/users/${name})
.then( (response) => response.json())
.then((data) => console.log(data);
};

 

Where's your try/catch block? You would get unhandled promise rejection error, also Fetch() doesn't handle failed HTTP responses, as some users mentioned already.

So what's the point of this article? MDN already has a bunch of useful examples: developer.mozilla.org/en-US/docs/W...

 

You rock, thanks for these examples!

 

Santiago beloqui, se usa el response.json() porque lo que devuelve la consulta no contiene el json directamente, sino contiene otras propiedades como el estado, etc.

Así que con esto obtenemos realmente la información en formato json.

 

Thank you for this wonderfully concise write-up! I'm working on improving some of my JavaScript blindspots, so this was a great way to come to grips with async and await

 

Hi Nick , how'd you recommend handling jwt tokens in this!! Actually i was trying to add my token to the localstorage and tried doing

localStorage.setItem('jwt','data.token)

But didn't work!!

 
 

Why is necessary the await for the "reponse.json()"?

 

Because the fetch api won’t return the data directly, therefore we need to use this .json() method to extract the body content from the http response.

Check this out
developer.mozilla.org/en-US/docs/W...

 

Muito bom artigo, acabei de me inscrever na comunidade.
Simples e direto ao ponto.

Consegui entender perfeitamente.

 

best shortest easiest to understand article ever. What are your thoughts about axios?