Search code examples
javascriptes6-promise

Precedence of .then() over code outside a Promise?


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.)


Solution

  • 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..