Its often said that async/await is just syntactic sugar over promises, and we can re-write code using one approach over other. Lets say I have this piece of code using promises:
async function main() {
const promise = new Promise((resolve) => {
return resolve('promise resolved value')
})
promise.then((res) => console.log(res))
console.log('after promise.then()')
}
main().then((res) => console.log('end'))
The output would be:
after promise.then()
promise resolved value
end
which makes sense.
Now the issue I have is if I re-write this code using async/await:
async function main() {
const asyncFunc = async () => {
return 'async func resolved value'
}
console.log(await asyncFunc())
console.log('after await asyncFunc()')
}
main().then((res) => console.log('end'))
The order of execution change:
async func resolved value
after await asyncFunc()
end
This is confusing to me, how should I rewrite the code using async/await so I would get the same order of execution?
2
Answers
First some comments on your scenario set-up:
The first code snippet has already an
async
keyword, which makes the conversion toasync/await
syntax a bit blurred — you didn’t start from a scenario where you didn’t use it.There seems no good reason why the original
main
function should be anasync
function as it doesn’t execute anawait
. All of its code (so excluding callbacks) executes synchronously.main
returns an immediately resolved promise. The only purpose that serves, is that you delay the execution ofconsole.log('end')
, but for that you could have done (withoutasync
):The immediately resolving promise called
promise
can also be created in a more simple way, usingPromise.resolve('promise resolved value')
The output "after promise.then()" is generated synchronously, independent of any promise. If you want to translate that to an
async/await
version, it should also occur at a place where it is independent of any promise, and therefore should certainly not be placed after anawait
operation.Not a big issue, but in the second snippet you have not created the promise in an assignment like in the first snippet. To align it more with the first snippet, you would immediately execute the async function and assign that promise to
promise
.Now to making it output in the same sequence with
async/await
, you could place the code that waits forpromise
to resolve in its ownasync
function, so that you can perform the ‘after then()’ output outside of it (ensuring it is independent from a promise, like in the first snippet)So I adapted the original code to not use
async
at all:And the following snippet could be a translation of that to
async/await
, where the onlyPromise#then
call is in the top-level code:As you can see, this does not make the code any more elegant or more readable. You should use the syntax that best suits the purpose.
And there really is no good reason to avoid the use of
Promise.resolve
when creating an immediately resolved promise. Usingasync
syntax for that is making your code more verbose and hard-to-read than needed.These pieces of code aren’t equivalent. The snippet with raw promises contains problems:
async
without a reasonmain
contains detached promise that isn’t returned, which is a bad practiceconsole.log
afterpromise.then(...)
.This is how it would be written with raw promises:
And fully equivalent
async..await
:Notice that a promise doesn’t exist in both cases before
'before then'
. In some cases it may be necessary to create a promise, do a synchronous operation and then wait for a promise, like shown in the original code with raw promises. In this case it would be changed to: