I am always curious that if a Promise is rejected at any position, will the following then()
still be executed? Take the codes below as an example:
Promise.reject('reJECTed')
.then(() => {
console.log('before resolve()');
return Promise.resolve('reSOLVed');
})
.then((msg) => {
console.log('reSOLVed inside 1st then()');
console.log(msg);
}, (msg) => {
console.log('reJECTed inside 1st then()');
console.log(msg);
})
.then((msg) => {
console.log('reSOLVing inside 2nd then()');
console.log(msg);
}, (msg) => {
console.log('reJECTing inside 2nd then()');
console.log(msg);
})
.catch((msg) => {
console.log('reJECTed in catch()');
console.log(msg);
});
It will print
reJECTed inside 1st then()
reJECTed
reSOLVing inside 2nd then()
undefined
on the console, which means the resolve()
in second then()
and the last catch()
were not executed. Does that mean when met reject()
, any following resolve()
s inside a then()
is totally skipped until the rejection is caught?
Thanks for any explanation!
Does that mean when met reject(), any following resolve()s inside a then() is totally skipped until the rejection is caught?
Yes. When a promise rejects, all resolve handlers in the chain are skipped up until some reject handler handles the rejection and changes the promise chain back to fulfilled.
And, in case you didn't realize, the 2nd argument to a .then()
handler is a reject handler (pretty much the same as a .catch()
handler).
But, keep in mind that if you have a reject handler and it does not throw
or return a rejected promise, then the chain becomes fulfilled again since you have "handled" the rejection. It's exactly like with try/catch
. If you catch
and don't rethrow, then the exception is handled and normal execution continues after that.
So, in your reject handler that outputs reJECTed inside 1st then()
, you are not returning anything so at that point the promise chain becomes fulfilled. The rejection has been "handled" at that point and the promise chain now switches to the fulfilled state.
Here's some annotation on your code:
Promise.reject('reJECTed')
.then(() => {
// this fulfilled handler is skipped because the promise chain is rejected here
console.log('before resolve()');
return Promise.resolve('reSOLVed');
})
.then((msg) => {
// this fulfilled handler is skipped because the promise chain is rejected here
console.log('reSOLVed inside 1st then()');
console.log(msg);
}, (msg) => {
// this reject handler is called because the promise chain is rejected here
console.log('reJECTed inside 1st then()');
console.log(msg);
// because this does not rethrow or return a rejected promise
// the promise chain switches to fulfilled
})
.then((msg) => {
// this fulfilled handler is called because the promise chain is fulfilled now
console.log('reSOLVing inside 2nd then()');
console.log(msg);
}, (msg) => {
// this reject handler is not called because the promise chain is fulfilled now
console.log('reJECTing inside 2nd then()');
console.log(msg);
})
.catch((msg) => {
// this reject handler is not called because the promise chain is fulfilled now
console.log('reJECTed in catch()');
console.log(msg);
});
Let me offer another example to show how a promise chain can switch states:
Promise.reject("Hello").then(val => {
console.log("1: I am not called");
}).catch(err => {
console.log("2: I am rejected");
// rethrow to keep promise chain rejected
throw err;
}).catch(err => {
console.log("3: I am still rejected");
// return normal value, promise chain switches to fulfilled
return "GoodBye";
}).then(val => {
console.log("4: Now back to fulfilled state");
}).catch(err => {
console.log("5: Not called");
});
Yes, this is described in Scenario B
Promise.reject will result in a rejected promise, which means
results in unhandled promise, if no then or catch
it will fallback to the first catch
or error hook specified by then
Promise.reject()
.then(
() => {},
() => { console.log ('Im called') } // goes here
)
Promise.reject()
.catch(() => { console.log('Im called as well') }) // or here
Remember that then
and catch
return either
Now everything goes carries on again from Scenario A or B, for instance
Promise.reject()
.catch(() => { return 5; }) // returns promise that resolves to 5,
.then(
res => console.log('See, Im not rejected and resolve to', 5),
() => {}
);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With