ES6 Promise.all()error handling – 是.settle()需要?

假设我有一个Promise.all()来处理两个promise。 如果一个承诺产生一个错误,但另一个承诺,我希望能够处理Promise.all()已经解决后的情况的基础上的错误。

ES6承诺错过了解决方法,我假设有一个很好的理由。 但是我不禁想到.settle()方法会让这个问题更容易。

我是以这种错误的方式去做的,还是用一种解决方法扩展ES6的承诺是正确的事情呢?

我想如何使用.settle()一个例子:

 Promise.all([Action1,Action2]) .settle(function(arrayOfSettledValues) //if 1 failed but not 2, handle //if 2 failed but not 1, handle //etc.... ) 

我是以这种错误的方式去做的,还是用一种解决方法来扩展ES6的承诺是正确的事情呢?

你不能直接使用Promise.all()来生成.settle()types的行为,因为Promise.all()是“快速失败”,并且只要第一个承诺拒绝,它只返回拒绝的原因,没有其他的结果。

所以,需要不同的东西。 通常,解决这个问题的最简单的方法就是在任何操作中添加一个.then()处理函数来创build你的promise数组,以便捕获任何拒绝,并将它们转化为具有某些可以testing的特定值的promise。 但是,这种types的解决scheme是依赖于实现的,因为它取决于你正在返回什么types的值,所以这不是完全通用的。

如果你想要一个通用的解决scheme,那么像.settle()这样的东西是非常有用的。

你不能使用这个结构:

 Promise.all([...]).settle(...).then(...); 

因为Promise.all()拒绝第一个通过的承诺,拒绝并且只返回拒绝。 .settle()逻辑的工作方式如下所示:

 Promise.settle([...]).then(...); 

而且,如果你有兴趣,下面是Promise.settle()的一个相当简单的实现:

 // ES6 version of settle Promise.settle = function(promises) { function PromiseInspection(fulfilled, val) { return { isFulfilled: function() { return fulfilled; }, isRejected: function() { return !fulfilled; }, isPending: function() { // PromiseInspection objects created here are never pending return false; }, value: function() { if (!fulfilled) { throw new Error("Can't call .value() on a promise that is not fulfilled"); } return val; }, reason: function() { if (fulfilled) { throw new Error("Can't call .reason() on a promise that is fulfilled"); } return val; } }; } return Promise.all(promises.map(function(p) { // make sure any values are wrapped in a promise return Promise.resolve(p).then(function(val) { return new PromiseInspection(true, val); }, function(err) { return new PromiseInspection(false, err); }); })); } 

在这个实现中, Promise.settle()将永远解决(永远不会拒绝),并用PromiseInspection对象数组来解决这个问题,它允许你testing每个单独的结果,看看它是解决还是拒绝,以及每个结果的价值或原因。 它通过附加一个.then()处理程序来处理传入的每个promise,处理这个promise中的resolve或reject,并将结果放入一个PromiseInspection对象,然后成为promise的parsing值。

然后你会这样使用这个实现;

 Promise.settle([...]).then(function(results) { results.forEach(function(pi, index) { if (pi.isFulfilled()) { console.log("p[" + index + "] is fulfilled with value = ", pi.value()); } else { console.log("p[" + index + "] is rejected with reasons = ", pi.reason()); } }); }); 

仅供参考,我自己编写了另一个.settle版本,我称之为.settleVal()而且当您不需要实际的拒绝原因时,我经常会发现它更容易使用,您只想知道给定的数组插槽是否被拒绝或不。 在这个版本中,你传递一个默认值,应该被任何被拒绝的承诺所替代。 然后,你只需得到一个返回值的平面数组,任何被设置为被拒绝的默认值。 例如,您通常可以select一个null0rejectVal""{} ,并使结果更容易处理。 这个function:

 // settle all promises. For rejected promises, return a specific rejectVal that is // distinguishable from your successful return values (often null or 0 or "" or {}) Promise.settleVal = function(rejectVal, promises) { return Promise.all(promises.map(function(p) { // make sure any values or foreign promises are wrapped in a promise return Promise.resolve(p).then(null, function(err) { // instead of rejection, just return the rejectVal (often null or 0 or "" or {}) return rejectVal; }); })); }; 

然后,你这样使用它:

 Promise.settleVal(null, [...]).then(function(results) { results.forEach(function(pi, index) { if (pi !== null) { console.log("p[" + index + "] is fulfilled with value = ", pi); } }); }); 

这不是对.settle()的完全替代,因为有时您可能想知道它被拒绝的实际原因,或者您无法轻易地区分拒绝的值和未拒绝的值。 但是,我发现超过90%的时间,这是更简单的使用。


这是我对.settle()最新简化, .settle()在返回数组中留下一个instanceof Error作为区分parsing值和拒绝错误的方法:

 // settle all promises. For rejected promises, leave an Error object in the returned array Promise.settleVal = function(promises) { return Promise.all(promises.map(function(p) { // make sure any values or foreign promises are wrapped in a promise return Promise.resolve(p).catch(function(err) { let returnVal = err; // instead of rejection, leave the Error object in the array as the resolved value // make sure the err is wrapped in an Error object if not already an Error object if (!(err instanceof Error)) { returnVal = new Error(); returnVal.data = err; } return returnVal; }); })); }; 

然后,你这样使用它:

 Promise.settleVal(null, [...]).then(function(results) { results.forEach(function(item, index) { if (item instanceof Error) { console.log("p[" + index + "] rejected with error = ", item); } else { console.log("p[" + index + "] fulfilled with value = ", item); } }); }); 

对于所有情况,这可以完全替代.settle() ,只要instanceof Error一个instanceof Error永远不是您的promise的parsing值(实际上不应该是这个值)。