Promise.resolve(1)
.then(x => console.log(1))
.catch(x => console.log(2))
.then(x => console.log(3))
Promise.reject(2)
.then(x => console.log(4))
.catch(x => console.log(6))
.then(x => console.log(7))
result is "1 6 3 7", but if i add another then() before catch with console.log(6) result will be 1 3 6 7, i dont’t understand why
Promise.resolve(1)
.then(x => console.log(1))
.catch(x => console.log(2))
.then(x => console.log(3))
Promise.reject(2)
.then(x => console.log(4))
.then(x => console.log(5))
.catch(x => console.log(6))
.then(x => console.log(7))
result is 1 3 6 7
i’m trying to understand how it works
2
Answers
You called
Promise.resolve
the first time, so thethen
callback will be called. Any subsequentthen
callbacks will also be called.Next, you called
Promise.reject
that means that everythen
callback will be ignored up to thecatch
callback (the rejection handler). However, once thecatch
handler is finished resolving (or finished returning something), if it didn’t throw an error, the nextthen
callback is called.Promise listeners are run by a Promise task runner job put in the Promise Job Queue when a promise becomes fulfilled or rejected. HTML 5 uses the microtask queue for the Promise Job Queue, and the queue operates as a FIFO (first in first out).
Promise Jobs are run consecutively, after other JavaScript has returned to the event loop, until the Promise Job queue is empty.
The purpose of a promise job is to pass the value or rejection reason of the promise that created the job onto the next promise in a chain of promises. If the promise spawning the job is fulfilled, the next promise will be fulfilled with the same value, and if rejected, rejected with the same reason. If a promise listener returns a promise, the next promise is resolved with the promise returned.
It’s worth mentioning that
catch
clauses are shorthand for a two argument call tothen
. Whether a clause in the source code saysthen
orcatch
, promise jobs are still created to resolve, fulfill or reject the promise object that the clause returned.Putting all this together should allow predicting the sequence of promise listener executions in cases when multiple promise chains are being processed at the same time.
The first example inter-meshes promise jobs in the following sequence:
The second example also inter-meshes program jobs but with a different alignment:
Moral of the story? Don’t depend on the execution order of multiple jobs in the promise queue, by breaking promise chains into smaller chains if you need partial completion results.