Async / Await is not a magical time-traveling pixie dust
This has been the death of many. And as one Rapropos put it…
Many have fallen into this trap (like I did before I understood) because they miss this one thing about Async /Await and to quote MDN
— in fact,
await
only works inside async functions…
Async/await makes your code look synchronous, and in a way it makes it behave more synchronously. Theawait
keyword blocks execution of all the code that follows until the promise fulfills, exactly as it would with a synchronous operation. It does allow other tasks to continue to run in the meantime, but your own code is blocked.
For example, someone looking at the code below without this understanding will expect
async function hello() {
return greeting = await new Promise((resolve, reject) => {
setTimeout(function(){
resolve('Success!');
}, 5000);
});
} // Call the async function
(function (){
console.log('about to call function hello');
hello().then(console.log);
console.log('function hello has been called');
})()
to produce
about to call function hello
Success!
function hello has been called
Only to be surprised it doesn’t work so because they thought the async /await would block the code where the function hello has been called, wait for it to resolve and the continue on. Woe unto you if you implement it like this in an API call expecting such synchronous behavior.
Instead here is the outcome.
When am using Async / Await one rule of thumb is:
await
will only blocks the code execution within theasync
function. It’ll make sure that next line(s) is/are executed when thepromise
resolves.
Assuming that our hello function returns / resolves to a value we need in the next line, we alter the code by moving async /await to the code that depends on hello function. This ensures that our code will wait for hello to resolve in order to be able to access and use its resolved value before continuing to other lines making it synchronous.
But then again be warned it could be disastrous if the promise takes for ever to resolve or never resolves, you would be perpetually waiting forever blocking the next line(s) of code.
In such a case we could have the promise constructor take an executor function that lets us resolve or reject a promise manually.
const wait = ms => new Promise(resolve => setTimeout(resolve, ms));
wait(10*1000)
.then(() =>
saySomething("10 seconds")
.catch(failureCallback);