When you provide a .catch()
handler or the second argument for .then()
, the rejected promise has been "handled". By default, when you provide such a reject handler, the promise system will assume that the rejection has been handled and the chain should continue.
If you don't want the chain to continue, then from the reject handler, you can either return a rejected promise or throw an error. That will then stop that chain up until another reject handler in the chain.
So, here are the possibilities in a chain like you show:
1) There is no reject handler in the chain
The chain is stopped entirely and no further .then()
fulfill handlers are executed.
2) There is a reject handler in the chain that either returns nothing or returns a regular value or a fulfilled promise or a promise that eventually fulfills.
This is what your code currently shows. The reject is considered handled and the promise state of the chain changes to a fulfilled promise so subsequent fulfillment handlers in the chain are called.
3) There is a reject handler in the chain that either returns a rejected promise or throws an error
Returning the rejected promise (or a promise that rejects in the future) or throwing a new error (which gets turned into rejected promise) will stop further processing of the chain up until the next error handler.
So, if you changed your onRejected()
handler to this:
function onRejected(error) {
 console.log(error);
throw error; // rethrow error to stop the rest of the chain
}
Then, your promise chain would stop there.
It's important to understand why it works this way. This allows you to handle an error in the middle of the promise chain and the code handling the error gets to decide whether the chain continues or not based on what it returns or throws. If it returns nothing or a normal value or a fulfilled promise, then processing of the chain continues - the error has been handled - no need to stop further processing.
But, if the error is more serious than that and processing should not continue, then the reject handler can either throw the same error or throw a different error or return a rejected promise and the chain will skip any fulfill handlers up until the next reject handler in the chain.