Suppose we have a Promise in an asynchronous function:
(async function() {
let x = 0;
await new Promise((resolve, reject) => {
setTimeout(() => resolve(), 2000)
})
.then(res => {
x = 100;
})
console.log(x);
})();
The console output is always 100
, and never 0
. I tried it in all major browsers and Node.js. This is exactly what I intended to see, but I sense code smell around it. I'm not sure if this is a safe way to pass a value to x
. It seems to work though, even if I put a lot of code before it. Unless it's something asynchronous (like another setTimeout()
) it's all good.
Can someone please confirm if the .then()
branch actually takes precedence and runs before the alert(x)
line, or is it happening only by chance?
(Yes, I know there are better ways to do this, but this is a simplified proof-of-concept snippet.)
It’s guaranteed because the await
blocks until the promise chain completes. This is because the .then
chained to the original promise returns a new promise, and the await
operates on that.
The expected behavior is that the console.log occurs ~2s from the time the function starts running (when the promise is resolved), after x is already assigned (as part of the promise chain).
For “code smell” — I would argue it is cleaner to return state from promises and avoid side-effects. However, given the limited scope and guaranteed execution ordering..