admin管理员组

文章数量:1289508

When does Promise resolve/reject actually add a micro task?

I read the Promise/A+ implementation code from here, and understood that task adding action is triggered after resolve() (the mentioned implementation do it by timer callback, but from GPT's info, it seems to be micro task in real Promise implementation, then the onFulfilleds queue on the chain will be executed one by one).

However, when I run the code below, I get the result I didn't expect:

function a() {
  return new Promise((resolve) => {
      resolve();

      new Promise((r) => {
          r();
      }).then(() => {
          console.log("1")
      });

  })
}

await a();
console.log("2");

or

new Promise((resolve) => {
      resolve();

      new Promise((r) => {
          r();
      }).then(() => {
          console.log("1")
      });

  }).then(() => {
     console.log("2")   
})

I expected both the code pieces will log 2 then 1, but they both log 1 then 2, why I expect so:

  1. the outer Promise's resolve() add a micro task (provided by then) to queue which logs 2
  2. the inner Promise's r() add a micro task to queue which logs 1
  3. According to FIFO principle, 2 then 1.

but the result is 1 then 2, what did I mis-understand, I want to know it so bad.

When does Promise resolve/reject actually add a micro task?

I read the Promise/A+ implementation code from here, and understood that task adding action is triggered after resolve() (the mentioned implementation do it by timer callback, but from GPT's info, it seems to be micro task in real Promise implementation, then the onFulfilleds queue on the chain will be executed one by one).

However, when I run the code below, I get the result I didn't expect:

function a() {
  return new Promise((resolve) => {
      resolve();

      new Promise((r) => {
          r();
      }).then(() => {
          console.log("1")
      });

  })
}

await a();
console.log("2");

or

new Promise((resolve) => {
      resolve();

      new Promise((r) => {
          r();
      }).then(() => {
          console.log("1")
      });

  }).then(() => {
     console.log("2")   
})

I expected both the code pieces will log 2 then 1, but they both log 1 then 2, why I expect so:

  1. the outer Promise's resolve() add a micro task (provided by then) to queue which logs 2
  2. the inner Promise's r() add a micro task to queue which logs 1
  3. According to FIFO principle, 2 then 1.

but the result is 1 then 2, what did I mis-understand, I want to know it so bad.

Share Improve this question asked Feb 20 at 19:16 Zexuan ChenZexuan Chen 31 bronze badge 1
  • In terms of the question in the title, this is possibly answered in "Are promise handlers cleared from memory after the promise is resolved?". Please comment if you find it answers the question. – traktor Commented Feb 20 at 22:19
Add a comment  | 

1 Answer 1

Reset to default 1

I understood that task adding action is triggered after resolve()

No; or: only when there is already registered callbacks. In general, what is delayed is the then callback execution (or await resumption), not the resolution of the promise itself.

the outer Promise's resolve() add a micro task (provided by then) to queue

Notice that the new Promise executor callback runs synchronously, so it has called resolve() before the .then() method call happens. There is no task to schedule yet when the promise is getting resolved.

So all what is happening in your examples is that you are creating immediately-resolved promises, and then attaching then handlers on them - the same as

const a = Promise.resolve(); // or new Promise(resolve => { resolve(); })
const b = Promise.resolve();
b.then(() => {
    console.log("1")
});
a.then(() => {
    console.log("2")   
});

Given it's the .then() call on the fulfilled promise where the microtask queuing happens, the output is not unexpected.

本文标签: javascriptWhen does Promise resolvereject actually add a micro taskStack Overflow