0

If I remember correctly Promises are supposed to catch an error when one is thrown at all times so that Promise.catch() can be used to handle that error. I don't recall any exceptions however when I throw an error inside setTimeout() this somehow doesn't work.

Can someone explain why this doesn't work? Or is it simply a bug in NodeJS?

Test code

// This works!
function async() {
        return new Promise(function (resolve, reject) {
                throw new Error('test');
        });
}

async().catch(function() {
        console.log('Ok: 1');
});


// This doesn't work..
function async_fail() {
        return new Promise(function (resolve, reject) {
                setTimeout(function() {
                        throw new Error('test');
                }, 1);
        });
}

async_fail().catch(function() {
        console.log('Ok: 2');
});
Dillen Meijboom
  • 961
  • 6
  • 13
  • 1
    Why do you need a `setTimeout` within the promise... if you are using `BlueBird`, shouldn't the `.delay` could work better? http://bluebirdjs.com/docs/api/promise.delay.html – David Espino Nov 10 '16 at 06:33
  • @DavidEspino You're right but what if one of the npm packages I use uses ```setTimeout```? Then my code would crash because ```Promise.catch``` doesn't trigger :/ I also like to know _why_ this happends. – Dillen Meijboom Nov 10 '16 at 06:37
  • And so... you don't have control on what the `setTimeout` will execute? if you have I think it is just matter or `resolving` or `rejecting` the promise within that function... right? Take a look to this http://stackoverflow.com/questions/22707475/how-to-make-a-promise-from-settimeout... maybe that could help... most of the `npm` packages are `callback` based... so I think if you have a package that internally executes a `setTimeout` ... 95% sure that you may have a `callback` option... if not... IMHO that's baaaad npm package :)... – David Espino Nov 10 '16 at 06:41
  • This is actually something you can use as a trick: see this [this answer](http://stackoverflow.com/questions/30715367/why-can-i-not-throw-inside-a-promise-catch-handler) – rabbitco Nov 13 '16 at 07:10

1 Answers1

0

You will never catch an Error that is thrown in setTimeout, because it executes async to the actual execution of the promise function. So the promise itself already finished (without any call to resolve or reject) when the function inside set timeout is called.

If you want the promise to fail based on an error inside setTimeout you will need to catch it manually and call reject:

setTimeout(function() {
     try{
          throw new Error('test');
     }catch(ex){
          reject(ex);
     }
}, 1);
Tobi
  • 375
  • 2
  • 7
  • or, he could use a promisified version of `setTimeout`, correct? – Tom Dec 19 '17 at 08:18
  • @Tom sure you can, but i don't know of a vanilla js version of such a promisified `setTimeout`, so it might depend on the library / wrapper you are using. In general i would expect any of these wrappers to catch errors inside setTimeout and reject your promise. – Tobi Jan 04 '18 at 07:57