ES6 Promise.all()错误句柄-是否需要.settle()?[重复]

ES6 Promise.all()错误句柄-是否需要.settle()?[重复],第1张

ES6 Promise.all()错误句柄-是否需要.settle()?[重复]

我是用错误的方式解决问题还是用解决方法扩展ES6 Promises在这里正确的事情?

您不能直接使用

Promise.all()
生成
.settle()
类型行为来获取所有结果,无论是否由于
Promise.all()
“快速失败”而拒绝,并在第一个promise拒绝后立即返回,并且仅返回该拒绝原因,而没有其他结果。

因此,需要一些不同的东西。通常,解决该问题的最简单方法是,仅在

.then()
创建诺言数组的任何 *** 作中添加处理程序,以便它捕获所有否决项并将它们转变为具有可测试的特定值的诺言。但是,这种解决方案的类型取决于实现,因为它完全取决于您要返回的值的类型,因此这不是完全通用的。

如果您想要一个通用的解决方案,那么类似的东西

.settle()
将非常有用。

您不能使用以下结构:

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

注意(于2019年添加):似乎Promise标准工作已被

Promise.allSettled()
选为“类似定居点”行为的标准实现。您可以在此答案的末尾看到更多信息。

因为

Promise.all()
当您通过第一个诺言时会拒绝,所以它会拒绝,并且仅返回该拒绝。该
.settle()
逻辑工作方式:

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

而且,如果您有兴趣,这里是一个相当简单的实现

Promise.settle()

// ES6 version of settlePromise.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
对象数组进行解析,该对象数组允许您测试每个单独的结果,以查看它是已解决还是被拒绝以及每个值或原因是什么。它通过
.then()
为传入的每个promise
附加一个处理程序来处理该promise的拒绝或拒绝,并将结果放入
PromiseInspection
对象,该对象随后成为promise的resolved值。

然后,您将使用这种实现方式;

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()
当您不需要实际的拒绝原因时,您只想知道给定的阵列插槽是否被拒绝,我经常发现它更易于使用。在此版本中,您传入一个默认值,该默认值应替代任何拒绝的承诺。然后,您只获得返回值的平面数组,并拒绝所有设置为默认值的值。例如,你经常可以挑选
rejectVal
null
0
""
{}
它使结果更容易对付。功能如下:

// 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()
,它
instanceof Error
在返回数组中保留了一个区分分辨值和拒绝错误的方法:

// settle all promises.  For rejected promises, leave an Error object in the returned arrayPromise.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
它永远不是您的诺言的可解决的价值(实际上是不应该的),这可以完全替代所有情况。


if (!Promise.allSettled) {    Promise.allSettled = function(promises) {        let wrappedPromises = Array.from(promises).map(p =>   this.resolve(p).then(      val => ({ state: 'fulfilled', value: val }),      err => ({ state: 'rejected', reason: err })  )        );        return this.all(wrappedPromises);    }}

用法如下:

let promises = [...];    // some array of promises, some of which may rejectPromise.allSettled(promises).then(results => {    for (let r of results) {        if (r.state === 'fulfilled') { console.log('fulfilled:', r.val);        } else { console.log('rejected:', r.err);        }    }});

请注意,

Promise.allSettled()
尽管后续
.then()
处理程序可能抛出或返回被拒绝的诺言以使整个链被拒绝,但它本身始终会解决,永远不会拒绝。

截至2019年6月,此功能尚未在当前的桌面Chrome浏览器中使用,但计划在即将发布的版本中使用(例如,在2019年晚些时候)。



欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5084158.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-11-16
下一篇 2022-11-16

发表评论

登录后才能评论

评论列表(0条)

保存