It depends on the implementation of the promise. If we check the spec. You can find the final spec here – since this answer was originally written, it has been finalized.
Here is the relevant excerpt (you can find the original source here)
- Let completion be Call(executor, undefined, «resolvingFunctions.[[Resolve]], resolvingFunctions.[[Reject]]»).
- If completion is an abrupt completion, then
- Let status be Call(resolvingFunctions.[[Reject]], undefined, «completion.[[value]]»).
- ReturnIfAbrupt(status).
The ES6 standard indicates that the fulfillment of a promise is always asynchronous (See section 25.4.5.3, Promise.prototype.then
and accompanying section 25.4.5.3.1, PerformPromiseThen
). I have placed the relevant material below.
PerformPromiseThen
- Else if the value of promise’s [[PromiseState]] internal slot is “fulfilled”,
- Let value be the value of promise’s [[PromiseResult]] internal slot.
- Perform EnqueueJob(“PromiseJobs”, PromiseReactionJob, «fulfillReaction, value»).
- Else if the value of promise’s [[PromiseState]] internal slot is “rejected”,
- Let reason be the value of promise’s [[PromiseResult]] internal slot.
- Perform EnqueueJob(“PromiseJobs”, PromiseReactionJob, «rejectReaction, reason»).
TLDR: the function passed to the promise is executed synchronously, but subsequent then
calls are always executed asynchronously.