When is the body of a Promise executed?

27,587

Solution 1

Immediately, yes, by specification.

From the MDN:

The executor function is executed immediately by the Promise implementation, passing resolve and reject functions (the executor is called before the Promise constructor even returns the created object)

Here it is in the ECMAScript specification (of course harder to read...): http://www.ecma-international.org/ecma-262/6.0/#sec-promise-executor

This guarantee may be important, for example when you're preparing several promises you then pass to all or race, or when your executors have synchronous side effects.

Solution 2

Yes, when you construct a Promise the first parameter gets executed immediately.

In general, you wouldn't really use a promise in the way you did, as with your current implementation, it would still be synchronous.

You would rather implement it with a timeout, or call the resolve function as part of an ajax callback

function doSomethingAsynchronous() {
  return new Promise((resolve) => {
    setTimeout(function() {
      const result = doSomeWork();
      resolve(result);
    }, 0);
  });
}

The setTimeout method would then call the function at the next possible moment the event queue is free

Solution 3

You can see from below the body is executed immediately just by putting synchronous code in the body rather than asynchronous:

function doSomethingAsynchronous() {
  return new Promise((resolve) => {
    console.log("a");
    resolve("promise result");
  });
}
doSomethingAsynchronous();console.log("b");

The result shows the promise body is executed immediately (before 'b' is printed):

a
b

The result of the Promise is retained, to be released to a 'then' call for example:

doSomethingAsynchronous().then(function(pr){console.log("c:"+pr);});console.log("b");

Result:

a
b
c:promise result

Same deal with asynchronous code in the body except the indeterminate delay before the promise is fulfilled and 'then' can be called (point 'c'). So 'a' and 'b' would be printed as soon as doSomethingAsynchronous() returns but 'c' appears only when the promise is fulfilled ('resolve' is called).

What looks odd on the surface, once the call to 'then' is added, is that 'b' is printed before 'c' even when everything is synchronous. Surely 'a' would print, then 'c' and finally 'b'? The reason why 'a', 'b' and 'c' are printed in that order is because no matter whether code in the body is async or sync, the 'then' method is always called asynchronously by the Promise.

In my mind, I imagine the 'then' method being invoked by something like setTimeout(function(){then(pr);},0); in the Promise once 'resolve' is called. I.e. the current execution path must complete before the function passed to 'then' will be executed.

Not obvious from the Promise specification why it does this. My guess is it ensures consistent behaviour regarding when 'then' is called (always after current execution thread finishes) which is presumably to allow multiple Promises to be stacked/chained together before kicking off all the then calls in succession.

Solution 4

From the EcmaScript specification http://www.ecma-international.org/ecma-262/6.0/#sec-promise-executor

The executor function is executed immediately by the Promise implementation, passing resolve and reject functions (the executor is called before the Promise constructor even returns the created object)

Consider the following code:

var executorFunction = (resolve, reject) => {
    console.log("This line will be printed as soon as we declare the promise");
    if(asyncTaskCompleted){
        resolve("Pass resolved Value here");
    }else{
        reject("Pass reject reason here");
    }

}
const myPromise = new Promise(executorFunction);

When we execute the above code, executorFunction will be called automatically as soon as we declare the promise, without us having to explicitly invoke it.

Share:
27,587

Related videos on Youtube

Kevin
Author by

Kevin

I write code, fiction, and music.

Updated on January 11, 2021

Comments

  • Kevin
    Kevin over 3 years

    Suppose I have the following Promise:

    function doSomethingAsynchronous() {
      return new Promise((resolve) => {
        const result = doSomeWork();
    
        setTimeout(() => {
          resolve(result);
       }), 100);
      });
    }
    

    At which point in time is doSomeWork() called? Is it immediately after or as the Promise is constructed? If not, is there something additional I need to do explicitly to make sure the body of the Promise is run?

    • Andreas
      Andreas about 7 years
    • ssube
      ssube about 7 years
      It doesn't matter: if you need to enforce order of operations, do so explicitly. Different implementations will handle promises with slight differences in behavior (bluebird vs native map, for example).
    • Kevin
      Kevin about 7 years
      @guest271314 I'm writing some tests and need to mock a function that returns a Promise. I want the Promises the mock returns to resolve immediately so that the tests run successfully, so I just wanted to double-check that there wasn't some kind of magic I had to invoke to get them to run.
    • Kevin
      Kevin about 7 years
      That, and I want to understand how Promises work under the hood.
    • Denys Séguret
      Denys Séguret about 7 years
      @Kevin Why are you adding this question with "If not" ? Did you see my answer ? It is guaranteed the executor is always immediately executed even before the Promise constructor returns. There's no "implementation details" here, it's specified.
    • Kevin
      Kevin about 7 years
      @DenysSéguret, yep, I saw your answer (and I'm likely to accept it). I added the third question to add some more context for why I was asking the question for future readers, but I don't need any more clarification myself.
    • jfriend00
      jfriend00 about 7 years
      This may help explain things: stackoverflow.com/questions/42031051/…. It covers a slightly more complicated situation (a promise within a promise), but definitely covers what is going on here, including what happens when a promise resolves before the .then() handlers are attached.
    • Denys Séguret
      Denys Séguret over 5 years
      Please don't close this question as a duplicate of one which only has bad answers. And no, this isn't implementation dependent but specified.
    • Bergi
      Bergi almost 5 years
  • Paleo
    Paleo over 6 years
    Immediately is confusing. The executor is really called synchronously by the Promise constructor.
  • dosentmatter
    dosentmatter over 3 years
    It seems that MDN and the ES spec doesn't say that anymore, but I think you can still assume it runs sync since the steps 1-11 mentions return a promise, which you do get back synchronously. It doesn't mention running it async or queueing it somewhere like how PerformPromiseThen says "Append fulfillReaction as the last element of the...".