我怎么知道哪些处理程序在承诺中抛出错误?
假设我有一个承诺如下:
p.then(Task1) .then(Task2) .then(Task3) .catch(errorHandler);
当Task2遇到错误时,如何知道错误是从Task2中捕获的 ?
大家! 我自己研究过演示代码。
我希望大家可以回顾一下我的答案,不pipe好不好。
介绍:
它显示了如何跟踪每个处理程序中的promise,使用自定义的error handling程序来捕获错误。 了解承诺的工作stream程。
您可以复制以下演示代码并粘贴到您的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
从上面的例子我们可以知道:
当input是'Task1'时,路线是:
firstHandler – > firstCatcher
当input是'Task2'时,路线是:
firstHandler – > secondHandler – > firstCatcher – > secondCather
当input是“Task3”时,路线是:
firstHandler – > secondHandler – > thirdHandler – > firstCatcher – > secondCatcher – > thirdCatcher
所以,从上面的结果我们知道,我们可以理解如何工作的承诺。
如果大家都对这个答案感到满意,请告诉我,谢谢。
由于承诺链不能保存这些信息,因此您需要将其存储在某个地方。 两种解决scheme
装饰错误:
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 }
大多数浏览器都支持error.stack
属性,一些现代浏览器甚至支持asynchronous调用堆栈:
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));
为了知道在所有浏览器中来自Task2
的最后一个catch中的(asynchronous)错误,你可以抓住它,给它加上标签并重新抛出它:
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
捕获错误,所以你还需要一个“绕过”的方法:
p.then(Task1) .then(result => Task2(result).catch(e => tag(e, "Task2"))) .then(Task3) .catch(errorHandler);
这使Task1
或更早的任何错误“绕过”(即绕过)我们的Task1
的捕获。
这是有效的,因为我们把catch放在了.then
的成功callback里面。 每一个.then
都有一个隐含的第二个参数,它是一个error handling程序,就像.catch
,除了它不捕获相应的成功callback,在这种情况下, Task2
和我们的catch,只有链上的前一个错误(即Task1
或任何先前的步骤)。
省略错误callback意味着“通过这个不变”。 即与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));
你可以这样做;
Promise.resolve(21).then(v => v*2) .then(v => { try { throw new Error(v + " is immutable") } // assuming that your code results an error catch(err){ return Promise.reject({message: "2nd then stage threw an error", err:err}) } }) .then(v => v) .catch(err => console.log(err.message, "\n",err.err.message));