【问题标题】:Why does VS Code break on handled exception from Reject in Promise?为什么 VS Code 在 Promise 中拒绝处理异常时会中断?
【发布时间】:2017-12-30 03:52:18
【问题描述】:

以这段代码为例,我们有一个调用会失败的函数的 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
节点 7.4.0

【问题讨论】:

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


    【解决方案1】:

    解决方案

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

    发生在在附加处理程序之前引发异常导致拒绝时。例如,这不会导致它,因为当异常转换为拒绝时,已经附加了一个拒绝处理程序:

    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 说:

    如果在附加错误处理程序之前拒绝了一个承诺,即使只检查了“未捕获的异常”,调试器也会中断。如果在附加错误处理程序后它被拒绝,它会按预期工作。 真正的问题是,promise 不知道它的拒绝是否会被处理。

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

    (我已经在vscode issue 上发表了评论,如果我学到任何有用的信息,我会更新这篇文章)

    编辑1:
    我发现另一种解决方法是在 vscode 中定义一个键绑定来运行命令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 在 cmets 中指出的那样:

    发生在在附加处理程序之前引发异常导致拒绝时。例如,这不会导致它,因为当异常转换为拒绝时,已经附加了一个拒绝处理程序:

    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
    });
    

    【讨论】:

    • “发生这种情况是因为 Nodejs 在遇到拒绝回调时会发送带有未定义异常的中断事件” 我不认为这是正确的。我认为它在抛出异常导致在附加处理程序之前被拒绝时发生。例如,这不会导致它,因为当异常转换为拒绝时,已经附加了一个拒绝处理程序:new Promise((resolve, reject) => setTimeout(() => { try { throw new Error(); } catch (e) { reject(e); } }, 0)).catch(error => console.log("Error:", error));
    • (无需标记编辑。只需编辑答案,使其在合理的时间内尽可能好。如果人们需要查看更改的历史,有一个链接。 )
    • @T.J.Crowder 我知道,这更像是一种强迫症
    猜你喜欢
    • 2017-09-02
    • 2016-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-27
    • 2021-04-28
    相关资源
    最近更新 更多