简体   繁体   中英

Promises: why is the resolve executed after sync code and before async one

I have the following code:

const doWorkPromise = new Promise((resolve, reject) => {
    setTimeout(() => {
        console.log('#2 (async call)');
    }, 0);
    resolve('#3 (async call?)');
    console.log('#1 (sync call)');
});

doWorkPromise.then((result) => {
    console.log('Success!', result);
}).catch((error) => {
    console.log('Error!', error);
});

The output is:

#1 (sync call)
Success? #3 (async call?)
#2 (async call)

I know that sync code lands on the call stack and the async code registers event-callback pair at the Node APIs, where the callback is moved to the callback queue after the event. The event loop is then going to take elements out of the callback queue only when the call stack is empty. Therefore, I expected to have the sync code executed first and then the async one in order, because the timeouts are 0s, like:

#1 (sync call)
#2 (async call)
Success? #3 (async call?)

Can someone please explain why resolve is executed before '#2 (async call)'?

reject is never executed.

resolved is executed before #2 because:

  1. setTimeout puts a function on the time out queue
  2. resolve resolves the promise
  3. console.log logs #1
  4. The function finished
  5. doWorkPromise.then assigns a function to run when the promise resolves
  6. The promise is already resolved so that function is executed
  7. After the minimum timeout time passes the function passed to setTimeout is called and logs #2

Your code executes the following synchronously :

resolve('#3 (async call?)');

...so that promise gets immediately in a resolved state. The fact that you have started a timer, as no bearing on the promise... it is unrelated.

So the then callback on that promise will be triggered on the next processing of the job queue, and so you'll see "Success", right after the execution of the main, synchronous code has completed.

Somewhat later (yes, even setTimeout(..., 0) will introduce a small delay), the timer will expire, but that event has nothing to do with any promise.

The common pattern

When you create a promise with new Promise and want it to resolve some time later, then you could indeed use setTimeout , but then the idea is to call resolve only when that timer has expired. Otherwise the timer does not do anything that serves the promise:

setTimeout(() => {
    resolve();
}, 0);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM