It chains just fine without the call to res()
in that the succeeding .then()
handlers are chained onto the original promise.
But, the original promise will never be resolved if you don't execute res(someValue)
so therefore, it will never call your .then()
handlers. At some point, you have to resolve the original promise at the start of the chain if you want any of the .then()
handlers to get called. Until you call res(someValue)
, you have a promise chain where the head of the chain is sitting in the pending
state waiting to be resolved or rejected so it can then run the rest of the chain.
But if I exclude the res(res), it will not chain. But it chains fine afterwards without any additional res().
The original promise has to be resolved before the first .then()
handler will get called. From then on, just returning from a .then()
handler resolves the next promise in the chain - you no longer have to manually resolve it.
From within a .then()
handler, you can trigger different outcomes three different ways:
Return from the .then()
handler. This resolves that chained promise and triggers its .then()
handlers to get called. If you return a value, that value becomes the new resolved value of this part of the chain. If you don't return a value or there's an implicit return, then the resolved value is undefined
.
Throw an exception from within the .then()
handler. This will be automatically caught by the promise infrastructure and will cause this promise in the promise chain to reject - trigger any .catch()
handler to get called.
Return a promise from the .then()
handler. This causes the current promise in the chain to track this new promise and it will resolve or reject based on what the newly returned promise does.
Also, a given promise can only be resolved or rejected once. It's a one-way state machine. Once it has been resolved or rejected, it's state is fixed and can not be changed again. So, you would only ever call res(someValue)
once. Attempting to call it more than once just does nothing as the promise has already been changed to the fulfilled
state and can no longer be changed.
FYI, the three states of a promise are pending
, fulfilled
and rejected
. When you call res(someValue)
, you change the state of the original promise in your chain from pending
to fulfilled
and the internals of the promise will then call its .then()
handlers on the next tick.
Something that people often don't realize is that each call to .then()
creates and returns a new promise that is linked to the earlier promise chain. So, the code in your question actually creates 3 promises, one from new Promise()
and two from the two calls to .then()
. These subsequent promises from calls to .then()
get resolved or rejected only when the parent promise gets resolved or rejected and the .then()
or .catch()
handler gets called and then there's a return value from that .then()
or .catch()
handler. Those return values from those handlers determine what happens next in the chain.