Sequence of rejected promise with Promise.reject()

I am learning microtask queue and i have a simple question.

With the following code:

Promise.resolve().then(()=>console.log("Resolved1 Promise"));
Promise.reject().then(()=>console.log("Resolved2 Promise")).catch(()=>console.log('Rejected2 Promise'));
Promise.resolve().then(()=>console.log("Resolved3 Promise"));
Promise.resolve().then(()=>console.log("Resolved4 Promise"));
Promise.resolve().then(()=>console.log("Resolved5 Promise"));

I expected output to be in the sequence:

Resolved1 Promise
Rejected2 Promise
Resolved3 Promise
Resolved4 Promise
Resolved5 Promise

But as you can try above, rejected callback is triggered in the last. Can anyone explain it to me?

Upvotes: 4

Views: 77

Answers (2)

MfyDev
MfyDev

Reputation: 530

This is because you're chaining .chatch() to the result of .then() function. This can be fixed by removing .then() from the promise:

Promise.resolve().then(() => console.log("Resolved1 Promise"));
Promise.reject().catch(() => console.log('Rejected2 Promise'));
Promise.resolve().then(() => console.log("Resolved3 Promise"));
Promise.resolve().then(() => console.log("Resolved4 Promise"));
Promise.resolve().then(() => console.log("Resolved5 Promise"));

Optionally, if you want to listen for both events, use a sigle .then() call to assign both listeners:

Promise.resolve().then(() => console.log("Resolved1 Promise"));
Promise.reject().then(
    () => console.log("Resolved2 Promise"),
    () => console.log('Rejected2 Promise')
);
Promise.resolve().then(() => console.log("Resolved3 Promise"));
Promise.resolve().then(() => console.log("Resolved4 Promise"));
Promise.resolve().then(() => console.log("Resolved5 Promise"));

Upvotes: 2

Unlucky
Unlucky

Reputation: 447

Code snippet:

Promise.resolve().then(()=>console.log("Resolved1 Promise"));
Promise.reject().then(()=>console.log("Resolved2 Promise")).catch(()=>console.log("Rejected2 Promise"));
Promise.resolve().then(()=>console.log("Resolved3 Promise"));

Output:

Resolved1 Promise
Resolved3 Promise
Rejected2 Promise

The output order is due to the following sequence of microtask queue operations:

Step Microtask Added to Queue Callback Executed Output
1 Promise.resolve().then() console.log("Resolved1 Promise") Resolved1 Promise
2 Promise.reject().then().catch() undefined (adds .catch() to the queue for step 4) no output yet
3 Promise.resolve().then() console.log("Resolved3 Promise") Resolved3 Promise
4 Promise.reject().then().catch() console.log("Rejected2 Promise") Rejected2 Promise

When the rejected promise skips .then(), its .catch() runs in the next microtask after the first .then() but before subsequent .then() callbacks:

Promise.resolve().then(()=>console.log("Resolved1 Promise"));
Promise.reject().catch(()=>console.log("Rejected2 Promise"));
Promise.resolve().then(()=>console.log("Resolved3 Promise"));

The .then() method accepts two optional arguments: onFulfilled (for resolved promises) and onRejected (for rejected promises). In this case, the second Promise.reject() can have an explicit onRejected in .then() that prevents the rejection from propagating to .catch(). For more details on onFulfilled and onRejected, see https://promisesaplus.com/#the-then-method.

Promise.resolve().then(()=>console.log("Resolved1 Promise"));
Promise.reject().then(undefined, ()=>console.log("Rejected2 Promise")).catch(()=>console.log("Rejected2 Promise"));
Promise.resolve().then(()=>console.log("Resolved3 Promise"));

Here's another example that shows that it doesn't matter if it's the catch or then, the next then/catch will be added to the microqueue only after the previous then/catch executes.

Promise.resolve().then().then().then(()=>console.log("Resolved1 Promise"));
Promise.reject().then().catch(()=>console.log("Rejected2 Promise"));
Promise.resolve().then(()=>console.log("Resolved3 Promise"));

Upvotes: 0

Related Questions