admin管理员组

文章数量:1135905

Suppose I have the following code constructing a 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 callback is run?

Suppose I have the following code constructing a 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 callback is run?

Share Improve this question edited Apr 3, 2023 at 19:31 dumbass 27.2k4 gold badges36 silver badges73 bronze badges asked Feb 8, 2017 at 16:45 KevinKevin 15.9k25 gold badges80 silver badges127 bronze badges 9
  • 4 ECMAScript, 25.4.3.1 Promise(executor) -> Step 9 – Andreas Commented Feb 8, 2017 at 16:49
  • 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). – ssube Commented Feb 8, 2017 at 16:52
  • 2 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. – jfriend00 Commented Feb 8, 2017 at 17:41
  • 1 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. – Denys Séguret Commented Sep 14, 2018 at 15:09
  • 1 possible duplicate of Is the Promise constructor callback executed asynchronously? – Bergi Commented Jul 27, 2019 at 16:42
 |  Show 4 more comments

4 Answers 4

Reset to default 106

It is called synchronously, yes, by specification.

From the MDN:

The executor is called synchronously (as soon as the Promise is constructed) with the resolveFunc and rejectFunc functions as arguments.

This is defined in the ECMAScript specification (of course, it's harder to read...) here (Step 9 as of this edit, showing that the executor is called synchronously):

  1. Let completion be Completion(Call(executor, undefined, « resolvingFunctions.[[Resolve]], resolvingFunctions.[[Reject]] »)).

(my emphasis)

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.

You can see 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).

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

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

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

Result:

a
b
c:promise result

The same deals with asynchronous code in the body except for 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 that no matter whether the 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(()=>{then(pr)},0) in the Promise once resolve is called. I.e. the current execution path must be 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 behavior regarding when then is called (always after the 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.

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

From the EcmaScript specification

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:

let asyncTaskCompleted = true

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

本文标签: javascriptWhen is the body of a Promise constructor callback executedStack Overflow