In my previous question, I found that once a Promise is resolved, no errors are caught that are thrown after resolve()
. Today, after experimenting a bit I noticed that this is not true if a setTimeout is used inside the Promise.
Example 1 - No error caught
var prom2 = new Promise(function(resolve, reject) {
resolve("THE_RESOLVE2");
throw Error("Not caught!")
sdf2;
});
Example 2 - error is caught in setTimeout
var prom2 = new Promise(function(resolve, reject) {
setTimeout(function(){
resolve("THE_RESOLVE2");
throw Error("Caught!")
sdf2;
}, 500);
});
If you can please explain in easy language, ecmascript documentation is hard for me to understand.
CodePudding user response:
In the first case, the throw
is directly inside the promise executor function where the try/catch
that it surrounds the call to the executor function with will catch the rejection. That rejection will be ignored because at that point, the promise has already been resolved so its state can't be changed.
In the second case, the throw
is inside the setTimeout()
callback which has an empty callstack (it comes directly from the event loop) and thus there is nobody to catch that throw
and the system will complain. The promise executor function has long since returned already so the throw
inside the setTimeout()
callback can't be caught by it. Remember when you call setTimeout()
, it schedules the timer and then immediately returns and your executor callback function that you passed new Promise()
returns (before the timer fires).
Here's an example of the implicit try/catch
internal the promise executor function. When you throw before calling resolve or reject, that throw will be caught internally by the promise and will reject the promise. But, if you've already called resolve or reject, the throw will still be caught internally, but the promise state is already set and can't be changed at that point so the try/catch that catches the throw just doesn't do anything with the throw (it just eats it).
Try running this demo:
function test() {
return new Promise((resolve, reject) => {
throw new Error("I threw it");
resolve("all done");
});
}
test().then(result => {
console.log("resolved:", result);
}).catch(err => {
console.log("rejected:", err.message);
});