dem*_*n85 119 javascript asynchronous throw promise es6-promise
为什么我不能Error在catch回调中抛出一个内部并让进程处理错误,就好像它在任何其他范围内一样?
如果我什么都不做console.log(err)就会被打印出去,我对发生的事情一无所知.这个过程刚刚结束......
例:
function do1() {
return new Promise(function(resolve, reject) {
throw new Error('do1');
setTimeout(resolve, 1000)
});
}
function do2() {
return new Promise(function(resolve, reject) {
setTimeout(function() {
reject(new Error('do2'));
}, 1000)
});
}
do1().then(do2).catch(function(err) {
//console.log(err.stack); // This is the only way to see the stack
throw err; // This does nothing
});
Run Code Online (Sandbox Code Playgroud)
如果回调在主线程中执行,为什么Error会被黑洞吞噬?
jib*_*jib 149
正如其他人所解释的那样,"黑洞"是因为投入内部是.catch一个被拒绝的承诺继续链,你没有更多的捕获,导致一个未终止的链,吞下错误(坏!)
再添一个捕获,看看发生了什么:
do1().then(do2).catch(function(err) {
//console.log(err.stack); // This is the only way to see the stack
throw err; // Where does this go?
}).catch(function(err) {
console.log(err.stack); // It goes here!
});
Run Code Online (Sandbox Code Playgroud)
当你希望链条尽管步骤失败时,链条中间的一个捕获是有用的,但重新抛出对于在记录信息或清理步骤之后继续失败很有用,甚至可能改变哪个错误被扔了.
为了使错误在Web控制台中显示为错误,就像您最初的预期一样,我使用了这个技巧:
.catch(function(err) { setTimeout(function() { throw err; }); });
Run Code Online (Sandbox Code Playgroud)
即使行号仍然存在,因此Web控制台中的链接将我直接转到发生(原始)错误的文件和行.
被称为promise履行或拒绝处理程序的函数中的任何异常都会自动转换为拒绝您应该返回的promise.调用您的函数的promise代码负责这一点.
另一方面,setTimeout调用的函数始终从JavaScript稳定状态运行,即它在JavaScript事件循环中以新的循环运行.没有任何东西可以捕获异常,并将其发送到Web控制台.由于err保存了有关错误的所有信息,包括原始堆栈,文件和行号,因此仍可正确报告.
the*_*eye 43
这里要了解的重要事项
无论是then和catch函数返回新承诺的对象.
投掷或明确拒绝,将当前承诺移至被拒绝的状态.
由于then与catch返回新的承诺的对象,它们可以被链接.
如果你在promise处理程序(then或catch)中抛出或拒绝,它将在链接路径下的下一个拒绝处理程序中处理.
如jfriend00所述,then和catch处理程序不是同步执行的.当一个处理程序抛出时,它会立即结束.因此,堆栈将被展开,异常将丢失.这就是为什么抛出异常会拒绝当前的承诺.
在你的情况下,你do1通过投掷一个Error对象来拒绝内部.现在,当前的承诺将处于拒绝状态,控制权将转移到下一个处理程序,这then在我们的例子中.
由于then处理程序没有拒绝处理程序,因此do2根本不会执行.您可以console.log在里面使用它来确认.由于当前的promise没有拒绝处理程序,它也会被前一个promise的拒绝值拒绝,控件将被转移到下一个处理程序catch.
作为catch拒绝处理程序,当您console.log(err.stack);在其中执行时,您可以看到错误堆栈跟踪.现在,您正在抛出一个Error对象,因此返回的承诺catch也将处于拒绝状态.
由于您没有附加任何拒绝处理程序,因此catch您无法观察到拒绝.
您可以拆分链并更好地理解这一点,就像这样
var promise = do1().then(do2);
var promise1 = promise.catch(function (err) {
console.log("Promise", promise);
throw err;
});
promise1.catch(function (err) {
console.log("Promise1", promise1);
});
Run Code Online (Sandbox Code Playgroud)
您将获得的输出将是类似的
Promise Promise { <rejected> [Error: do1] }
Promise1 Promise { <rejected> [Error: do1] }
Run Code Online (Sandbox Code Playgroud)
在catch处理程序1中,您将promise对象的值视为已拒绝.
同样的方式,catch处理程序1 返回的promise 也promise被拒绝,并且被拒绝的错误与我们在第二个catch处理程序中观察它一样.
我尝试了setTimeout()上面详述的方法...
.catch(function(err) { setTimeout(function() { throw err; }); });
Run Code Online (Sandbox Code Playgroud)
恼人的是,我发现这是完全无法测试的。因为它抛出一个异步错误,所以你不能把它包装在一个try/catch语句中,因为在catch抛出错误时它将停止监听。
我恢复到只使用一个完美的监听器,因为它是 JavaScript 的使用方式,所以是高度可测试的。
return new Promise((resolve, reject) => {
reject("err");
}).catch(err => {
this.emit("uncaughtException", err);
/* Throw so the promise is still rejected for testing */
throw err;
});
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
74341 次 |
| 最近记录: |