为什么VS代码在承诺中拒绝处理的异常? [英] Why does VS Code break on handled exception from Reject in Promise?

查看:572
本文介绍了为什么VS代码在承诺中拒绝处理的异常?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

采取这个代码,我们有一个承诺,调用一个失败的函数,它应该将错误传递给承诺的catch方法。


从终端运行时工作正常。
但是当通过vscode运行时,它会在(1)中爆炸。

  function failingFunc(){
let undef = undefined;
return undef.nope();
}
let promise = new Promise((resolve,reject)=> {
resolve(failingFunc()); //(1)从vscode
} );
promise.then(v => {})catch((e:Error)=> {
console.log(e.message); //(2)终端
});

为什么是这样?



vscode关于页面:

版本1.14.2

提交cb82feb

日期2017-07-19T23:26:08.116Z

Shell 1.6.6

Renderer 56.0.2924.87

Node 7.4.0

解决方案

解决方案



As @TJCrowder 在评论中指出:


仅当引发异常导致处理程序附加前的拒绝时,才会发生此 。例如,这不会导致它,因为当异常被转换为拒绝时,已经附加了拒绝处理程序:




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






原来这是一个已知的错误使用vscode调试Nodejs。
正如,如果我学到任何有用的话将更新此帖子)



Edit1:

我发现另一个解决方法是在vscode中定义一个键绑定来运行命令 workbench.action。 debug.run 。这将运行当前所选的调试选项,而不将调试器附加到它。这意味着您可以在需要处理拒绝承诺的情况下使用新的密钥命令运行代码,使调试器保持正常设置。

  / * keybindings.json * / 
[
{
key:ctrl + shift + b,
command:workbench.action .debug.start
/ *附加调试器* /
},
{
key:ctrl + b,
command:workbench .action.debug.run
/ *运行没有调试器* /
}
]

编辑2:

由于 @TJCrowder 在评论中指出:


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




  new Promise((resolve,reject)=> setTimeout(()=> {
try {
throw new Error();
} catch ){
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); //无法读取未定义的属性nope
});


Take this code, we have a promise that calls a function that will fail, and it should pass the error onward to the catch method of the promise.
It works just fine when ran from the terminal. However when ran through vscode it explodes at (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
});

Why is this?

vscode about page:
Version 1.14.2
Commit cb82feb
Date 2017-07-19T23:26:08.116Z
Shell 1.6.6
Renderer 56.0.2924.87
Node 7.4.0

解决方案

Solution

As @T.J.Crowder pointed out in the comments:

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


Turns out this is a known "bug" when using vscode to debug Nodejs. As its explained in this issue (over at the vscode git repository) this happens because Nodejs send a break-event with an undefined exception when ever it encounters a reject callback. When vscode's debugger sees this break-event it does what its supposed to do with unknown exceptions, it pauses the execution and then throws the exception.
Further more in this issue (over at the vscode-node-debug2 repository) @roblourens says that:

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.

You can still use vscode for developing Promise based systems, however you will need to turn off all error handling in vscode, as seen below make sure neither of the options are ticked. NOTE: Since this is far from an optimal solution, it is likely to get changed and or improved in the future.

(I've commented on the vscode issue and will update this post if I learn anything useful)

Edit1:
I've found that another workaround is to define a keybinding in vscode to run the command workbench.action.debug.run. This will run the current selected debug option without attaching the debugger to it. This means that you can keep the debugger on your normal settings, while running the code using the new key command when you need to work with rejected promises.

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

Edit2:
As @T.J.Crowder pointed out in the comments:

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

And of course he was right. The code below does work in vscode with the debugger attached.

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

这篇关于为什么VS代码在承诺中拒绝处理的异常?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆