"Synchronous" fetch with async/await
John Paul Ada

John Paul Ada @johnpaulada

About: BA Psychology grad turned software engineer. Tech Evangelist. Data Engineer.

Location:
Mandaluyong City, Philippines
Joined:
Jun 5, 2017

"Synchronous" fetch with async/await

Publish Date: Jul 20 '17
190 22

Originally posted at Medium.

TL;DR

async/await allows us to program using asynchronous requests in a "synchronous" manner using the modern versions of Javascript.

A hypothetical introduction

As web developers, we make requests to APIs a lot – not only to our own APIs but to others’, too. As we all know, they can be a real pain in the ass.

What if we wanted to make a request to a hypothetical API https://api.com ?

What if I told you, you can make requests like this in Javascript?

const response = fetch('https://api.com/values/1');
const json = response.json();
console.log(json);
Enter fullscreen mode Exit fullscreen mode

Normally, this would be impossible, and normally you’d do something like this:

fetch('https://api.com/values/1')
    .then(response => response.json())
    .then(json => console.log(json));
Enter fullscreen mode Exit fullscreen mode

That is less readable than the former example.

Although, if you try the former example, it wouldn’t work. Why, you ask? Well folks, we’re missing the magic words!

await

await allows us to wait for the response of an asynchronous request.

To use awaitin our hypothetical code, we can do this:

const response = await fetch('https://api.com/values/1');
const json = await response.json();
console.log(json);
Enter fullscreen mode Exit fullscreen mode

Let’s break this down.

In the first line, we make a GET request to https://api.com/values/1. Instead of continuing to the next line, we wait for the request to finish, hence await. When it finishes, it passes the resolved value to the response variable.

In the second line, we get the JSON version of the response. Again, we use await so we can wait for it to complete (or fail) and then pass the result to the json variable.

Finally, in the last line, we log the value of the json variable to the console.

This saves us from writing less-than-adequately-readable code allows us to write cleaner code.

This is a more intuitive way of working with requests.

To help you understand it more, here’s another way of looking at this:

await allows us to wait for a Promise to resolve to a value.

await will return the value only after the Promise is resolved.

Sorry for being redundant but this is so you’d understand. 😄 😅

async

But wait, there’s more! Not really, but there’s something I haven’t told you yet. You know that code we rewrote with await? It won’t work yet.

WHAT!? Ikr.

To make it work, you need to wrap it inside an async function!

This is how you do it:

const request = async () => {
    const response = await fetch('https://api.com/values/1');
    const json = await response.json();
    console.log(json);
}

request();
Enter fullscreen mode Exit fullscreen mode

You just add the async keyword before the function declaration and run it! EZ!

But don’t just take it from me! Try it out here! Just hit the Run button:

async/await Runkit example.

Hit the heart, unicorn or hands up button below if you like this post! 💙
Thanks! 👍

Comments 22 total

  • Ben Halpern
    Ben HalpernJul 21, 2017

    I've mostly stayed on the sidelines in terms of the new JavaScript features, but I'm starting to get back into it, and async await is something I look forward to playing with.

  • dann1609
    dann1609Feb 23, 2018

    if fetch end in catch this Will Block the app.

    • Moustache Design
      Moustache DesignMar 8, 2018

      Yes, indeed. You can prevent it by wrapping those lines in a try / catch block

  • rolivo
    rolivoMar 14, 2018

    Well i think that javacript is a s.hit because is for default async
    and it's a nightmare is synchronizing processes. Fetch api and cors are more s.hit
    they do not bring anything new, it's the same as ajax but with more pain.

    • Anthony Yershov
      Anthony YershovSep 12, 2019

      That's because fetch is meant to be as bare bones as possible. Ajax is there to make fetch cleaner.

  • gt-novelt
    gt-noveltJun 1, 2018

    I find more readable :

    const json = await fetch('https://api.com/values/1')
                    .then(response => response.json());
    console.log(json);
    
    Enter fullscreen mode Exit fullscreen mode

    Fetch returns a promise, no need to wrap this in an async function.

    • Ervin Wirth
      Ervin WirthDec 12, 2019

      Not working...
      SyntaxError: await is only valid in async functions and async generators

  • uclaeamsavino
    uclaeamsavinoOct 16, 2018

    Yo dog I heard you like await, so I put an await inside your await:

    const data = await (await fetch('https://api.com/values/1')).json();

    It would be nice if fetch offered a one-step method to get straight to the JSON data.

    How do you get the nice sublime font colors?

    • John Paul Ada
      John Paul AdaJan 22, 2019

      LOL
      You could create a function for that.
      I just create a javascript code block in markdown for the colors. :)

  • Alexander Hristoskov
    Alexander Hristoskov Jan 3, 2019

    I have the following problem, I have an express API endpoint which returns a token, although the promise .then() returns SyntaxError: JSON.parse: unexpected end of data at line 1 column 1 of the JSON data like the Promise is still not resolved. Anyone else have such issues? I tried your code as well but with the same result.

    • John Paul Ada
      John Paul AdaJan 22, 2019

      Hey! When I get this error, it's usually because the result I get isn't in JSON. Try await response.text() and check the response.

  • regs01
    regs01Feb 11, 2019

    await can only be used in async function. yes, it does wait for a promise, but function is still being run asynchronously. so when response is ready, the function to return this response has already ended.

    so quit a pointless construction.

  • Stephen 🇬🇧 🇺🇸 🇸🇾 🇰🇵
    Stephen 🇬🇧 🇺🇸 🇸🇾 🇰🇵Feb 17, 2019

    This is a great article, very new to this area and this is something that's been bugging me for days. I knew there had to be a better way to do what i wanted and this is it.

    Plenty of examples out there going off on tangents or using jQuery etc - and also pointed me in the direction of something to read up on further.

  • Archs
    ArchsMar 12, 2019

    your request function doesn't return the json result, only logs it. The function still returns a promise in my code, is it normal behavior? should the request function be sync when called as

    const res = request()

    ?

    • John Paul Ada
      John Paul AdaMar 13, 2019

      ahh the function wrapping that should also be async, so it should be like:

      const useRequest = async () => {
        const res = await request()
      }
      
      useRequest()
      

      given that you return the json instead of just logging it in the request() function.

  • venkatgadicherla
    venkatgadicherlaAug 17, 2019

    Hi
    May be I am a bit naive. But this bit of code not working for me. I am trying to put this in a react component in componentDidMount to get data from asp.net controller and getting various errors. Any pre-requisites for this code to work.

  • petko3000
    petko3000Oct 4, 2019

    Guys, i would like to solve one issue with this async function. How to load output from that function to a variable usable in later non-async code? Like lets say i collect data from couple of APIs within async function, then i need to do some logic on top of that data with non-async code.

    • spine001
      spine001Mar 22, 2021

      You can pass an objetc to the function, and then take care to only change the content of the object without making a copy of it, then what is passed is the address of the object. And when you modify it with methods of the object that don't make copies, you will be modifying the object itself outside the scope of the function.
      I imagine that you already solved this but since I haven't seen anybody ever give you an answer I am posting this to help others with the same problem.

  • mauroca80
    mauroca80Nov 5, 2019

    great!!!!!!! thanks for all

  • Dmitriy Popovich
    Dmitriy PopovichFeb 27, 2020

    (async () => {
    const todo = await Model.create(
    {
    //data
    }
    );
    const todoItem = await todo.save();

    })();
    
Add comment