2016-11-10 59 views
0

如果我没有记错的话Promise应该在任何时候抛出一个错误,以便可以使用Promise.catch()来处理该错误。我不记得任何例外,但是当我在setTimeout()内部抛出一个错误时,这种方式不起作用。承诺没有正确捕捉到错误NodeJS

有人可以解释为什么这不起作用吗?或者它只是NodeJS中的一个错误?

测试代码

// 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'); 
}); 
+1

为什么你需要在承诺中的'setTimeout' ...如果你正在使用'BlueBird',不应该'.delay'能更好地工作吗? http://bluebirdjs.com/docs/api/promise.delay.html –

+0

@DavidEspino你说得对,但如果我使用的npm包之一使用'''setTimeout'''会怎么样?然后我的代码会崩溃,因为''Promise.catch'''不会触发:/我也想知道_why_这发生了什么。 –

+0

所以......你无法控制'setTimeout'会执行什么?如果你有我认为这只是物质或“解决”或“拒绝”该功能的承诺......对吗?看看这个http://stackoverflow.com/questions/22707475/how-to-make-a-promise-from-settimeout ...也许这可能有帮助...大多数'npm'包是'callback '基于...所以我认为如果你有一个内部执行'setTimeout'的包... 95%确定你可能有一个'回调'选项...如果没有...恕我直言,这是baaaad npm包:) ... –

回答

0

你将永远不会赶上了在setTimeout的抛出一个错误,因为它执行异步的承诺函数的实际执行。因此,当设置超时内的函数被调用时,承诺本身已经完成(没有任何调用来解析或拒绝)。

如果你想在承诺失败是里面的setTimeout一个错误,你需要手动和呼叫抓住它拒绝:

setTimeout(function() { 
    try{ 
      throw new Error('test'); 
    }catch(ex){ 
      reject(ex); 
    } 
}, 1); 
+0

或者,他可以使用setTimeout的promisified版本,对吗? – Tom

+0

@确定你可以,但我不知道这样一个promisified'setTimeout'的vanilla js版本,所以它可能取决于你正在使用的库/包装。一般而言,我希望这些包装中的任何一个能够在setTimeout内部发现错误并拒绝您的承诺。 – Tobi