I am learning promise chaining and I stumbled upon a doubt. Consider the below promise chain –
const myPromise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("foo");
}, 10000);
});
myPromise
.then(handleFulfilledA, handleRejectedA) // first then
.then(handleFulfilledB, handleRejectedB) // second then
.then(handleFulfilledC, handleRejectedC); // third then
The promise constructor returns a promise object myPromise
. The handleFulfilledA
and handleRejectedA
are attached to the [[PromiseFulfillReactions]]
and [[PromiseRejectReactions]]
of myPromise
object. The second and the third then
method will be called before myPromise
is resolved as myPromise
takes 10 seconds.
What happens internally when the second and the third .then method is encountered?
I tried to find an answer and came to know that each then
method returns a new Promise
object. Let’s call them promiseB
and promiseC
. The handleFulfilledB
and handleRejectedB
are attached to the [[PromiseFulfillReactions]]
and [[PromiseRejectReactions]]
of promiseB
. Similarly, handleFulfilledC
and handleRejectedC
are attached to promiseC
.
But if this is the case, when myPromise
is fulfilled and its [[PromiseFulfillReactions]]
are executed, how will its reactionhandlers(handleFulfilledA
, handleRejectedA
) know that it has to resolve or reject promiseB
? How will the handler come to know that the then
to which it was passed to has created a promise which is promiseB
? In other words, how is the connection between the handlers and the new promises established?"
2
Answers
As per the MDN documentation for the then method:
This should explain why the chaining is possible.
handleFulfilledA
orhandleRejectedA
will not directly resolve or reject thepromiseB
.The promise returned by the first
then
method call, i.e.promiseB
depends on two things:myPromise
, andIn your code, as
myPromise
will be resolved,handleFulfilledA
will be called, and depending on what you do inside this handler,promiseB
will either resolve or get rejected.If you return any non-promise value, or implicitly return
undefined
,promiseB
will be fulfilled with that value as its fulfillment value.Similarly, if you throw an error inside the fulfillment handler of
myPromise
, thepromiseB
will get rejected with the thrown error as the rejection reason.Finally, what if you return a promise from the fulfillment handler? In that case,
promiseB
will get resolved to that promise. This simply means that fate of thepromiseB
will depend on the promise returned from the fulfillment handler ofmyPromise
. ThepromiseB
will fulfill if the promise returned by thethen
handler is fulfilled. Similarly,promiseB
will get rejected if the promise returned by thethen
handler is rejected.Following code example should give you an idea of how outer promise (
promiseB
) can resolve to the inner promise (returned by thethen
handler):Recommened reading: Javascript promises … in wicked detail