Async/await in javascript

Javascript is a single threaded language, that means that javascript uses a cooperative model of multi-tasking. In this approach a running task will give control back to the event loop until it needs to do something else and then it will gain control once more [emphasis mine]. In simple english what this means is when you have an async function calling another async function, the first function pauses at each await point until the second function returns its results, and only then does the first continue executing. This can lead to some unexpected behavior in certain cases.

Let’s see some examples:

Here we have two async functions which return promises that resolve in 200ms and 100ms respectively.

The main function simply waits for both promises to resolve and logs the results.

The output of this code will be “Async 1, Async 2”.

 

Running this in chrome gives us the following result:

As you can see, there’s a huge gap between these two lines which means that something is wrong. The reason for this behavior is that when await returns control to it’s caller, any code after that point will not be executed until the awaited task has completed. In our case this means that once PromiseA(..) has returned control, PromiseB(..) still has 100ms left before it completes its promise. The event loop sees this and runs another non-blocking task instead of blocking on PromiseB(…) . This results in a large gap between each line being printed even though they’re both only 200 ms apart.

When you use async/await and do not await anything, the async function returns a promise which represents its future value:

console.log(wait(5));
console.log(waitAsync(10, 20).then(function (x) {
    console.log(x * 2)
}));

Here both asnyc functions return promises that resolve asynchronously after 5 and 10 seconds respectively. The first call to wait(5) does not actually pause at this line but instead immediately resolves the returned promise by waiting for 5 seconds before it prints “Async 1” on the next line.  The second function however is inside another async function so it pauses at this line and only continues once the 10 seconds have passed. The next two lines then print “Async 1” and 20 respectively after 5 seconds each.

If we wanted to make both these tasks wait for 5 seconds before printing their results, we could do something like this:

var waitFive = function () {
    return new Promise(resolve => {
        setTimeout(resolve, 5000);
    });
};
async function waitAsync(time, msg) {
    await new Promise(resolve => setTimeout(resolve, time));
    console.log(msg * 2 + ' - ', await waitFive());
    console.log(msg * 2 + ' - ', await waitFive());
}

This is how you mix both async await and setTimeout s. Since wait(..) is an async function it returns a promise that resolves after 5 seconds. One cool thing about promises is that if you resolve them with another promise or value, it will wait for that promise to resolve before continuing.  Because of this, each call to wait(5) pauses execution until the returned promise has resolved (at which point it logs the number “5”). At this time control returns to PromiseA(…) which waits 100ms before resolving that promise with the number “10”. The rest of the execution is pretty self-explanatory. A few interesting things to note are that wait(5) resolves immediately but waits 5 seconds before actually returning control to its caller, this means you can call multiple await s on it within a single async function without it blocking anything! Also if you wanted to make every line in your entire asynchronous program wait for 5 seconds, you would simply do await new Promise(resolve => setTimeout(resolve, 5000)) .

 

async function getData() {
const response = await fetch("http://localhost:3000/api/v1/data");
const data = await response.json();
console.log(data);
}

 

 

Leave a Comment