seg*_*ult 7 javascript promise es6-promise
据MDN称:
如果任何传入的承诺拒绝,则所有承诺立即拒绝拒绝的承诺的价值,放弃所有其他承诺,无论他们是否已经解决.
该ES6规格似乎证实了这一点.
我的问题是:如果他们中的任何人拒绝,为什么Promise.all放弃承诺,因为我希望它等待"所有"承诺解决,"丢弃"究竟是什么意思?(很难说"丢弃"对于飞行中的承诺与可能尚未运行的承诺意味着什么.)
我问,因为我经常遇到一些情况,我有一份承诺清单,并希望等待他们全部解决,并得到可能已经发生的所有拒绝,这Promise.all是不满足的.相反,我必须使用这样的黑客:
const promises = []; // Array of promises
const settle = promise => promise.then(result => ({ result }), reason => ({ reason }));
Promise.all(promises.map(settle))
.then(/ * check "reason" property in each element for rejection */);
Run Code Online (Sandbox Code Playgroud)
与promises关联的异步操作都已运行.如果其中一个承诺拒绝,那么Promise.all()就不等待所有承诺完成,它会在第一个承诺拒绝时拒绝.这就是它的设计工作方式.如果您需要不同的逻辑(就像您希望等待所有这些逻辑完成,无论它们是满足还是拒绝),那么您就不能使用它Promise.all().
请记住,承诺不是异步操作本身.promise只是一个跟踪异步操作状态的对象.因此,当您传递一系列承诺时Promise.all(),所有这些异步操作都已经启动并且已经在进行中.它们不会被停止或取消.
为什么Promise.all抛弃了承诺,如果他们中的任何一个拒绝,因为我希望它等待"所有"承诺解决.
它的工作方式与它的工作方式相同,因为它是如何设计的,当你不希望代码在有任何错误的情况下继续时,这是一个非常常见的用例.如果它碰巧不是你的用例,那么你需要使用一些.settle()具有你想要的行为的实现(你似乎已经知道了).
我发现更有趣的问题是为什么.settle()规范和标准实现中没有选项,因为它也是一个相当常见的用例.幸运的是,正如您所发现的那样,创建自己的代码并不是很多.当我不需要实际的拒绝原因并且只想将一些指标值放入数组时,我经常使用这个相当简单的版本:
// settle all promises. For rejeted 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).catch(function(err) {
// instead of rejection, just return the rejectVal (often null or 0 or "" or {})
return rejectVal;
});
}));
};
// sample usage:
Promise.settleVal(null, someArrayOfPromises).then(function(results) {
results.forEach(function(r) {
// log successful ones
if (r !== null) {
console.log(r);
}
});
});
Run Code Online (Sandbox Code Playgroud)
"丢弃"究竟是什么意思?
它只是意味着承诺不再被追踪Promise.all().与它们相关联的异步操作始终保持正在执行的任何操作.事实上,如果这些承诺上有.then()处理程序,它们就会像通常那样被调用. discard在这里使用似乎是一个不幸的术语.除了Promise.all()停止关注它们之外什么也没发生.
仅供参考,如果我想要一个更强大的版本来.settle()跟踪所有结果并拒绝原因,那么我使用这个:
// ES6 version of settle that returns an instanceof Error for promises that rejected
Promise.settle = 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) {
// make sure error is wrapped in Error object so we can reliably detect which promises rejected
if (err instanceof Error) {
return err;
} else {
var errObject = new Error();
errObject.rejectErr = err;
return errObject;
}
});
}));
}
// usage
Promise.settle(someArrayOfPromises).then(function(results) {
results.forEach(function(r) {
if (r instanceof Error) {
console.log("reject reason", r.rejectErr);
} else {
// fulfilled value
console.log("fulfilled value:", r);
}
});
});
Run Code Online (Sandbox Code Playgroud)
这解决了一系列结果.如果结果是instanceof Error,那么它被拒绝,否则它是一个满足的值.
因为Promise.all保证他们都成功了。就那么简单。
与一起是最有用的构建块Promise.race。其他所有内容都可以基于这些内容。
有没有settle,因为它是如此微不足道打造这样的:
Promise.all([a(), b(), c()].map(p => p.catch(e => e)))
Run Code Online (Sandbox Code Playgroud)
没有简单的方法可以Promise.all在之上构建settle,这可能就是为什么它不是默认值的原因。settle还必须标准化一种将成功值与错误区分开的方法,这可能是主观的,并取决于情况。
| 归档时间: |
|
| 查看次数: |
3355 次 |
| 最近记录: |