Home > OS >  Why is error lodged after resolve() in a Promise, when setTimeout is used?
Why is error lodged after resolve() in a Promise, when setTimeout is used?

Time:12-02

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);    
});

  • Related