5

Is it possible to have user code executed between a promise resolution and a promise await return?

function a () {
  return new Promise(resolve => {
    setTimeout(() => {
      // Between here...
      resolve()
    }, 1000))
  }
}

async function b () {
  await a()
  // ...and here ?
}

Does the specification enforces that Promise callbacks are called immediatly? I wonder if an event could be handled by the virtual machine between the 2 points, possibly causing side-effects.

Yovar
  • 540
  • 1
  • 3
  • 16
  • Sure, that is what *asynchronous* means. Other events may happen interspersed between events. – deceze Jul 25 '17 at 09:27
  • Not an *event*, but other promise callbacks might run between there. – Bergi Jul 25 '17 at 09:35
  • 1
    @deceze I understand that anything could happen while b is waiting for a, but my question is specifically about between promise resolution and callbacks invocation. – Yovar Jul 25 '17 at 09:35
  • @Bergi Thank you indeed if the Promise has several callbacks multiple will be called, so I have to be aware of that. For the event part do you have any source? – Yovar Jul 25 '17 at 09:37
  • @Yovar Haven't found anything better than [this](https://stackoverflow.com/q/25915634/1048572) – Bergi Jul 25 '17 at 10:06
  • @Bergi Thank you, I suppose it works like the job system James Thorpe [refers to in his answer](https://stackoverflow.com/a/45299328/7243207). – Yovar Jul 25 '17 at 10:43

2 Answers2

5

No, it doesn't enforce immediate calling. The spec runs through a number of steps upon resolving a promise, one of which is:

  1. Perform EnqueueJob ("PromiseJobs", PromiseResolveThenableJob, «‍promise, resolution, thenAction»)

Note that depending on the state of the promise, different routes can be taken. However, they all end at EnqueueJob, which says:

  1. Add pending at the back of the Job Queue named by queueName.

So any further executions are deferred to the end of the job queue.

James Thorpe
  • 31,411
  • 5
  • 72
  • 93
2

Promise callbacks are not called immediately. Your function b() transforms to

function b () {
  return a().then(() => {
    // Do something
  });
}

where the function which is given to then is executed at some point of time by the eventloop after the promise from a was resolved. It will never be called synchronously, because the specification guarantees that Promise continuations always run with an empty call stack (which means in a fresh iteration of the eventloop). Therefore some other code (e.g. from another promise resolval) can run between the time where the promise was resolved and when the continuation runs.

Matthias247
  • 9,836
  • 1
  • 20
  • 29