Promise resolve and event loop

06 Mar, 2018Node.js, JavaScript

Because original has been resolved, its state is inherited by new Promise

This sentence is not correct, it is very simple to verify:

const p1 = new Promise((resolve) => {
  resolve(Promise.resolve());
});
console.log(p1); // pending

const p2 = new Promise((resolve) => {
  Promise.resolve().then(() => {
    resolve();
  });
});
console.log(p2); // pending

You can see that the parameter of the Promise's constructor is the executor function. It resolves another Promise when it is executed. Even if the state of the Promise is "resolved", it will not immediately change the state of the promise object when the constructor returns. Set to "resolved", actually "pending".

But if resolve(original) and original.then((value) => resolve(value)) are equivalent, the result should be 4 3 2 1). Because this resolve(value) is not executed synchronously in the first event loop, but it is the first to join the microtask queue. Explain that V8's processing of the call timing of the executor's resolve function is not synchronous. Some other Promise implementations (such as bluebird) are synchronous, and the result is indeed 4 3 2 1.

The processing of V8 seems to be equivalent to the following code. After reading this, both the result and the Promise state during execution are consistent:

const original = Promise.resolve(2);
new Promise((resolve) => {
  process.nextTick(() => {
    original.then((value) => {
      resolve(value);
    })
  });
  Promise.resolve().then(() => Promise.resolve().then(() => console.log(1)));
  console.log(4);
}).then(t => console.log(t));
console.log(3);

In general, the resolve of the executor is likely to be specially processed in the V8 Promise implementation. The execution of resolve(original) is not in the synchronous code, but is added to the microtask queue. When executed in the microtask queue, because it resolves another Promise, which is equivalent to the then result of resolve this Promise, it is added to the end of the microtask queue. When it is finally the turn of resolve(value) to execute, it has already been "jumped in" by a callback of Promise.resolve().then() and another callback brought by this callback, so resolve The execution of (value) is ranked last.

I didn't look at the code of V8 specifically, just analyzed it from the performance. But this is indeed something that is not mentioned in the specification, and it is related to implementation.


Powered by Gatsby. Theme inspired by end2end.

© 2014-2021. Made withby mdluo.