javascript - 为什么 VS Code 会中断来自 Reject in Promise 的已处理异常?

标签 javascript node.js exception promise visual-studio-code

拿这段代码来说,我们有一个调用函数的 promise 会失败,它应该将错误传递给 promise 的 catch 方法。
从终端运行时它工作得很好。 但是,当通过 vscode 运行时,它会在 (1) 处爆炸。

function failingFunc() {
    let undef = undefined;
    return undef.nope();
}
let promise = new Promise((resolve, reject) => {
   resolve(failingFunc()); // (1) Explodes when run from vscode
});
promise.then(v => {}).catch((e: Error) => {
    console.log(e.message); // (2) Prints when run from the terminal
});

这是为什么?

vscode 关于页面:
版本 1.14.2
提交 cb82feb
日期 2017-07-19T23:26:08.116Z
外壳 1.6.6
渲染器 56.0.2924.87
Node 7.4.0

最佳答案

解决方案

正如 @T.J.Crowder 在评论中指出的那样:

This only happens when an exception is thrown causing a rejection before a handler is attached. E.g., this wouldn't cause it, because when the exception is converted to rejection, there's already a rejection handler attached:

new Promise((resolve, reject) => setTimeout(() => { 
    try { 
        throw new Error(); 
    } catch (e) { 
        reject(e); 
    } 
}, 0)).catch(error => console.log("Error:", error));

事实证明,这是使用 vscode 调试 Nodejs 时的一个已知“错误”。 正如其在 this issue 中所解释的那样(在 vscode git 存储库中)发生这种情况是因为 Nodejs 在遇到 reject 回调时发送带有 undefined 异常的中断事件。当 vscode 的调试器看到这个中断事件时,它会执行它应该对未知异常执行的操作,它会暂停执行,然后抛出异常。
更多信息请参见 this issue (在 vscode-node-debug2 存储库中)@roblourens 说:

If a promise is rejected before an error handler is attached, the debugger will break, even if only "uncaught exceptions" is checked. If it's rejected after the error handler is attached, it works as expected. And really the problem is the way the promise doesn't know whether its rejection will be handled or not.

您仍然可以使用 vscode 开发基于 Promise 的系统,但是您需要关闭 vscode 中的所有错误处理,如下所示,确保没有勾选任何选项。 注意:由于这远非最佳解决方案,因此将来可能会进行更改或改进。

(我对 vscode issue 发表了评论,如果我学到任何有用的东西,我会更新这篇文章)

编辑1:
我发现另一种解决方法是在 vscode 中定义一个键绑定(bind)以运行命令 workbench.action.debug.run。这将运行当前选定的调试选项,而不会将调试器附加到它。这意味着您可以将调试器保持在正常设置,同时在需要处理被拒绝的 promise 时使用新的键盘命令运行代码。

/* keybindings.json */
[
    {
        "key": "ctrl+shift+b",
        "command": "workbench.action.debug.start"
        /* Attaches debugger */
    },
    {
        "key": "ctrl+b",
        "command": "workbench.action.debug.run"
        /* Runs without debugger */
    }
]

编辑2:
正如 @T.J.Crowder 在评论中指出的那样:

This only happens when an exception is thrown causing a rejection before a handler is attached. E.g., this wouldn't cause it, because when the exception is converted to rejection, there's already a rejection handler attached:

new Promise((resolve, reject) => setTimeout(() => { 
    try { 
        throw new Error(); 
    } catch (e) { 
        reject(e); 
    } 
}, 0)).catch(error => console.log("Error:", error));

当然他是对的。下面的代码在带有调试器的 vscode 中工作。

function failingFunc() {
    let undef = undefined;
    return undef.nope();
}
let promise = new Promise((resolve, reject) => {
    setTimeout(() => {
        try {
            resolve(failingFunc())
        } catch (e) {
            reject(e);
        }
    }, 0);
});
promise.then(v => {}).catch((e: Error) => {
    console.log(e.message); // Cannot read property 'nope' of undefined
});

关于javascript - 为什么 VS Code 会中断来自 Reject in Promise 的已处理异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45282653/

相关文章:

javascript - 在 jQuery 中用 div 包装逗号分隔的项目

javascript - 在不改变 iframe 高度的情况下改变 iframe 滚动条高度

javascript - Jquery和localStorage如何向网站clipdoard/cart添加更多元素

node.js - 错误 [ERR_STREAM_DESTROYED] : Cannot call write after a stream was destroyed

java.util.InputMismatchException : For input string: "2147483648"

javascript - Midnight Commander 可以识别光标键的什么代码?

windows - 将 node-webkit 应用程序打包为 ".appx"(适用于 Windows 8 商店)

javascript - Redis递归:超出最大调用堆栈大小

php - 从 PHP 中的自定义错误处理程序中抛出异常

java - 什么是Java : NoSuchElementException error?