假设我有以下承诺:
p.then(Task1)
.then(Task2)
.then(Task3)
.catch(errorHandler);
当 Task2 遇到错误时,我怎么知道错误来自 catch 中的 Task2 ?
答案 0 :(得分:2)
大家好!我自己研究了演示代码。
我希望每个人都可以查看我的答案,不管是好还是不好。
简介:
它显示了如何在每个处理程序中跟踪promise,使用自定义错误处理程序来捕获错误。要了解承诺的工作流程。
您可以复制以下演示代码并粘贴到 node.js 中。根据示例和日志消息,开发人员学习承诺是有益的。
使用的承诺模块如下:
演示的代码如下:
var Promise = require('bluebird');
// You can input any argument in this function to test workflow of promise
function testPromise(input) {
let promise = Promise.resolve(input);
promise
.then(makeTask('Task1'))
.then(makeTask('Task2'))
.then(makeTask('Task3'))
.catch(makeErrorPredicate('Task1'), taskLog('Task1'))
.catch(makeErrorPredicate('Task2'), taskLog('Task2'))
.catch(makeErrorPredicate('Task3'), taskLog('Task3'))
}
// define task handler functions
function makeTask(task) {
return function task1Handler(input) {
if (input === task) {
throw new Error(task)
}
return input
}
}
// custom error that it checks error message
function makeErrorPredicate(msg) {
return function taskError(err) {
var result = err.message === msg;
console.log(msg + ': ' + result)
return result;
}
}
// hint the error when the error has matched
function taskLog(msg) {
return function thelog(err) {
console.log('It\'s ' + msg)
}
}
示例:
>testPromise('Task1')
Task1: true
It's Task1
>testPromise('Task2')
Task1: false
Task2: true
It's Task2
>testPromise('Task3')
Task1: false
Task2: false
Task3: true
It's Task3
从上面的例子我们可以知道:
当输入是' Task1'时,路线为:
firstHandler - > firstCatcher
当输入是'任务2'时,路线是:
firstHandler - > secondHandler - > firstCatcher - > secondCather
当输入为'任务3'时,路线为:
firstHandler - > secondHandler - > thirdHandler - > firstCatcher - > secondCatcher - > thirdCatcher
因此,从上面的结果我们知道,我们可以理解如何工作的承诺。
如果每个人都对这个答案感到满意,请告诉我,谢谢。
答案 1 :(得分:1)
由于承诺链无法保存此信息,因此您需要将其存储在某处。两种解决方案:
p.then(Task1)
.then(function() {
try {
Task2();
} catch (e) {
e.isFromTask2 = true;
throw e;
}
})
.then(Task3)
.catch(errorHandler); // now you can check err.isFromTask2
{
let isFromTask2 = false;
p.then(Task1)
.then(function() {
try {
Task2();
} catch (e) {
isFromTask2 = true;
throw e;
}
})
.then(Task3)
.catch(errorHandler); // now you can check isFromTask2
}
答案 2 :(得分:0)
为了知道所有浏览器中来自Task2
的最终捕获中的(异步)错误,您可以捕获它,标记它并重新抛出它:
var tag = (e, name) => (e.isFrom = name, Promise.reject(e));
p.then(Task1)
.then(Task2)
.catch(e => tag(e, "Task2"))
.then(Task3)
.catch(errorHandler);
不幸的是,这也会抓住Task1
和p
的错误,所以你还需要一个" catch-bypass":
p.then(Task1)
.then(result => Task2(result).catch(e => tag(e, "Task2")))
.then(Task3)
.catch(errorHandler);
这会导致来自Task1
或更早版本的任何错误"绕过" (即绕过)我们的Task2
。
这是有效的,因为我们将catch放在.then
的成功回调中。每个.then
都有一个隐含的第二个参数,它是一个错误处理程序,就像.catch
一样,除了它没有捕获相应的成功回调,在这种情况下Task2
和我们的捕获,只有链上的先前错误(即来自Task1
或任何前一步骤的错误)。
省略错误回调意味着"通过未更改的"传递它。即与e => Promise.reject(e)
相同。
let tag = (e, name) => (e.isFrom = name, Promise.reject(e));
let a = () => Promise.resolve();
let b = () => Promise.reject(new Error("Fail"));
let c = () => Promise.resolve();
let x = () => null.f();
let foo = failFirstStep => Promise.resolve()
.then(failFirstStep? x : a)
.then(() => b().catch(e => tag(e, "b")))
.then(c)
.catch(e => console.log((e.isFrom || "something else") + " failed"));
foo(false).then(() => foo(true));

总而言之,你可以改为标记功能,但我觉得很难以一种惯用的方式做,并且不会干扰可读性或时间安排,所以我要离开作为一项运动。在实践中,有一个better answer,但我发现这种技术足够有趣,可以覆盖,并且在某些情况下很有用。
答案 3 :(得分:0)
大多数浏览器都支持error.stack
属性,一些现代浏览器甚至支持异步调用堆栈:
let a = () => Promise.resolve();
let b = () => Promise.reject(new Error("Fail"));
let c = () => Promise.resolve();
Promise.resolve().then(a).then(b).then(c).catch(e => console.log(e.stack));
在Firefox 48中输出:b@http://stacksnippets.net/js:14:30
。
在Chrome 52中输出:Error: Fail at b (http://stacksnippets.net/js:14:30)
。
这是最惯用的解决方案,因为它不会干扰代码的编写方式。不幸的是,并非所有浏览器都支持异步调用堆栈,并且输出在浏览器之间略有不同,因为它用于调试。
答案 4 :(得分:-1)
你可以这样做;
setlocal /?