为什么下面的代码无法捕获错误? ' catch'不工作和错误抛出并退出。我在nodeJs 8.9上运行代码
new Promise(function(resolve,reject){
console.log('construct a promise...')
setTimeout(() => {
throw new Error('async operation failure!')
},1000)
})
.then(() => {
//never happen
console.log('happen?wrong!!!')
})
.catch(e => {
console.warn('execute promise failure! catch it')
})
如果删除了setTimeout,那么' catch'作品
new Promise(function(resolve,reject){
console.log('construct a promise...')
throw new Error('async operation failure!')
})
.then(() => {
//never happen
console.log('happen?wrong!!!')
})
.catch(e => {
console.warn('execute promise failure! catch it')
})
为什么会这样? 请帮助,谢谢!
答案 0 :(得分:2)
setTimeout()
拥有自己的异步回调。该回调中的异常仅返回到计时器事件系统,它们不会转到其他任何地方,因此承诺无法捕获它们。您应该从reject(...)
内拨打setTimeout()
。
new Promise(function(resolve,reject){
console.log('construct a promise...')
setTimeout(() => {
reject(new Error('async operation failure!'));
},1000)
})
答案 1 :(得分:1)
要理解为什么你不能在setTimeout
的回调中抛出错误,你需要理解一些概念。
作为程序运行的信息存储在称为堆栈的数据结构中。调用方法时,信息将存储在堆栈中,直到方法返回为止。由于方法通常包含对其他方法的调用,因此堆栈会增长和缩小,直到所有方法都返回(这通常是程序的结束)。当抛出一个错误时,它会传递给尚未返回的函数调用堆栈,直到它被捕获和处理,或者到达" main"方法,通常会导致程序崩溃。
事件循环是Javascript中异步功能的动力。当调用setTimeout
或任何其他异步方法时,回调被放置在称为事件循环的队列中。当javascript运行时执行程序并到达堆栈的末尾(例如,所有方法都已返回)而不是仅仅退出程序时,它首先查看事件循环中是否有任何内容,如果有它开始执行它导致堆叠再次增长和收缩。当事件循环中没有任何内容,并且堆栈为空时,程序可以自由退出。
这意味着当您调用setTimeout
时,传递给方法的回调最终会在不同的堆栈帧中执行。这意味着错误不可能被丢弃到堆栈中并被promise承载,因为承诺创建的堆栈已经完成执行并且不再存在。
我建议观看有关该主题的视频,它会详细介绍并帮助您了解正在发生的事情:What the heck is the event loop anyway?