javascript - 为什么 promise 无法捕获 setTimeout 抛出的错误?

标签 javascript promise

<分区>

为什么下面的代码无法捕捉到错误? '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')
})

为什么会这样? 请帮忙,谢谢!

最佳答案

要理解为什么不能直接从 setTimeout 的回调中抛出错误,您需要了解一些概念。

堆栈

当程序运行时,信息存储在称为堆栈的数据结构中。当调用方法时,信息将存储在堆栈中,直到方法返回。由于方法通常包含对其他方法的调用,因此堆栈会增长和收缩,直到所有方法都返回(这通常是程序的结尾)。当错误被抛出时,它会向下传递到尚未返回的函数调用堆栈,直到它被捕获和处理,或者到达“main”方法,这通常会导致程序崩溃。

事件循环

事件循环为 Javascript 中的异步功能提供支持。当 setTimeout 或任何其他异步方法被调用时,回调被放置在称为事件循环的队列中。当 javascript 运行时执行程序并到达堆栈的末尾(例如,所有方法都已返回)而不是仅仅退出程序时,它首先查看事件循环中是否有任何东西,如果有它开始执行它导致堆栈再次增长和收缩。当事件循环中没有任何剩余且堆栈为空时,程序可以自由退出。


这意味着当您调用 setTimeout 时,传递到方法中的回调最终会在不同的堆栈帧中执行。这意味着错误不可能被抛出堆栈并被 promise 捕获,因为创建 promise 的堆栈已经完成执行并且不再存在。

我建议观看有关该主题的视频,它非常详细,可以帮助您直观地了解正在发生的事情:What the heck is the event loop anyway?

关于javascript - 为什么 promise 无法捕获 setTimeout 抛出的错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48969591/

相关文章:

javascript - Three.js objloader + 纹理

javascript - 如何在替换功能中输入多个span标签

javascript - SweetAlert2 和 promise

javascript - Promise 映射并获取数组的当前值

javascript - 尽管有 catch block ,但 fetch 仍然会抛出异常

ios - PromiseKit 6.0 将捕捉到的错误传递给调用者

javascript - 如何为 JVector Map 设置背景颜色?

javascript - 我需要在 JS 中的 url 旁边添加 HTML "value"的 "select/option"。您知道该怎么做吗?

javascript - 单个表单按钮错误地触发两个事件监听器和警报框

javascript - 了解 promise 链