This has been the death of many. And as one Rapropos put it on the Ionic Framework forum...
Many have fallen into this trap (like I did before I understood) because they miss this one thing about Async/Await. To quote MDN:
— in fact,
awaitonly works inside async functions... Async/await makes your code look synchronous, and in a way it makes it behave more synchronously. Theawaitkeyword 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.
The Common Misconception
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 then continue on. Woe unto you if you implement it like this in an API call expecting such synchronous behavior.
The Actual Output
Instead here is the outcome:
about to call function hello
function hello has been called
Success!
The Rule of Thumb
When using Async/Await, one rule of thumb is:
awaitwill only block the code execution within theasyncfunction. It'll make sure that next line(s) is/are executed when thepromiseresolves.
The Correct Approach
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 the 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:
(async function (){
console.log('about to call function hello');
const result = await hello();
console.log(result);
console.log('function hello has been called');
})()
Important Warning
But then again be warned: it could be disastrous if the promise takes forever to resolve or never resolves. You would be perpetually waiting forever, blocking the next line(s) of code.
Handling Long-Running Promises
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);
This article was originally published on Medium.