21

Suppose I have this code

function y(resolve, reject) { console.log("Result"); resolve(); } var promise = new Promise(y); 

What I want to know is whether the function y will be executed asynchronously or not.

15
  • 1
    No. y() will be executed synchronously. Within y(), calls to setTimeout(), AJAX requests, or similar would result in resolve() or reject() being executed asynchronously, but that's not the case in the code you posted. Commented Apr 30, 2015 at 8:53
  • 1
    Because promises compose well and provide a unified abstraction for that behaviour. Otherwise you just end up with callback soup. Just because the behaviour of the component is simple doesn't mean you don't want the component. For example, Array.forEach could very well just be a standard for loop. But Array.forEach looks nicer and allows the user to not worry about the implementation of for loops to use it. Commented Apr 30, 2015 at 9:33
  • 2
    Promises allow you to write Promise(x).then(y).then(z) instead of x(function(){y(function(){z()})}) that's all. It doesn't change how javascript fundamentally work Commented Apr 30, 2015 at 9:35
  • 1
    It just changes the way your code look. Nothing more. But keep in mind that code that's easy to reason about are also easier to debug so how a code looks is not unimportant Commented Apr 30, 2015 at 9:36
  • 1
    The benefits of promises really come apparent when you want to compose asynchronous operations. It is difficult to wait on a set of asynchronous callbacks without the use of a helper library, such as async, for example. Promises also enable you to write asynchronous code in nearly the same way as synchronous code (and with yield in ES6 we'll get even closer to that). Commented Apr 30, 2015 at 9:39

2 Answers 2

18

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)

  1. Let completion be Call(executor, undefined, «resolvingFunctions.[[Resolve]], resolvingFunctions.[[Reject]]»).
  2. 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

  1. 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»).
  2. 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.

Sign up to request clarification or add additional context in comments.

11 Comments

The mozilla version is easier to read though, as the official ones are in PDF
I'll stick it in just in case, there might be some discrepancies especially to future readers (though the spec is on the final draft so it is unlikely)
In the future, this answer will be outdated and irrelevant (I should know, I have lots of js answers go that way from way back) :D
Here's to hoping it's not.. :P I've put the final draft spec in, there was one discrepancy but it was fairly minor.
There is no official spec since it's a draft. Trust me this won't change.
|
10

The other answer proves this, but let me talk about the reasoning:

Promise constructor

The promise constructor callback (as specified either in the ES6 spec or the constructor spec libraries implement) will always be executed synchronously - this is in order to extract a deferred (older form of promise construction) out of it in case you need to have access to the resolve callback:

var r; var p new Promise(function(resolve, reject){ r = resolve; }); // use r here, for example arr.push(r); 

then callbacks

then will always be executed asynchronously, virtually all mainstream promise implementations (Native, bluebird, $q, Q, when, rsvp, promise, jQuery (as of 3.0) etc) as well as native promises implement (or implement a superset of, with more constraints) Promises/A+.

This is exactly the reason that Promises/A+ was created out of Promises/A. Asynchronous guarantees will be preserved and Zalgo won't be released. (Also see this post).

The fact this happens (asynchronous guarantee) is completely intentional and actively prevents race conditions. Code in- and outside of then will always execute in the same order.

Here is the relevant quote:

onFulfilled or onRejected must not be called until the execution context stack contains only platform code. [3.1].

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.