实现混合的承诺.所有的和承诺,解决
Implementing a mix of Promise.all and Promise.settle
我需要实现一个版本的Promise.all
,它会接受一个数组的承诺,并像往常一样返回结果,再加上解决所有的承诺,就像Promise.settle
在Bluebird
库中做的那样,除了我不能使用Bluebird
,并且必须依赖标准的承诺协议。
实现起来会非常复杂吗?或者在这里问一个如何实现它的想法是不是太过分了?我真的希望没有,所以我请求,如果有人以前实现过它,分享一下如何正确地做它的想法。
这样做的前提是能够在调用完成后需要执行commit
/rollback
的数据库事务中使用它,并且它不能有松散的承诺仍然试图在事务调用之外解决。
EDIT:提供的另一个问题的链接非常有用,但它不是所问问题的完整答案。通用的settle
是一个很好的例子,它帮助很大,但它需要被简化并包装成all
逻辑,以适应前面描述的事务场景。
我认为jfriend的解决方案过于复杂,因为它建立在settle
之上,它运行一个信号量,并做了很多奇怪的事情,而不是使用内置的原语,如.all
。
相反,如果我们构建蓝鸟的较新的reflect
原语(在本机承诺中实现它),我们可以得到一个更干净的API和实现:
function reflect(promise){
return promise.then(x => ({state: "fulfilled", value: x}), // arrows, assume nodejs
e => ({state: "rejected" , value: e}));
}
在reflect之上,我们可以很容易地构建其他原语:
function settle(promises){
return Promise.all(promises.map(reflect)); // much cleaner
}
如果我们想等待,然后根据值解析/拒绝,只需:
function allWait(promises){
return settle(promises).then(results => {
var firstFailed = results.find(r => r.state === "rejected");
if(firstFailed) throw firstFailed.value;
return results;
});
}
在另一个问题的通用promiseSettle()
函数的基础上,您可以这样做,并拥有通用settle()
类型函数和更具体的版本作为它的包装器。这将使您能够执行许多.settle()
类型的行为,并拥有自己的特定风味,还可以根据需要构建其他特定风味:
那么,这里是通用的promiseSettle()
,它返回所有承诺的状态,并且只有在所有传入的承诺完成时才会解析:
function promiseSettle(promises) {
return new Promise(function(resolve) {
var remaining = promises.length;
// place to store results in original order
var results = new Array(remaining);
function checkDone() {
if (--remaining === 0) {
resolve(results);
}
}
promises.forEach(function(item, index) {
// check if the array entry is actually a thenable
if (typeof item.then === "function") {
item.then(function(value) {
// success
results[index] = {state: "fulfilled", value: value};
checkDone();
}, function(err) {
// reject error
results[index] = {state: "rejected", value: err};
checkDone();
});
} else {
// not a thenable, just return the item itself
results[index] = {state: "fulfilled", value: item}
--remaining;
}
});
// special case for zero promises passed
if (remaining === 0) {
resolve(results);
}
});
}
这里有一个包装,它给了你特定的行为:
// Either fulfills with an array of results or
// rejects with the first error, but it does not do either
// until all promises have completed which makes it different than
// promise.all()
function promiseSettleAll(promises) {
return promiseSettle(promises).then(function(results) {
for (var i = 0; i < results.length; i++) {
if (results[i].state !== "fulfilled") {
// reject with the first error found
throw results[i].value;
}
}
// all were successful, return just array of values
return results.map(function(item) {return item.value;});
});
}
在所有的研究、编写、测试和优化之后,它变成了一个专注于这类事情的库(spex)。
具体来说,方法批处理是实现所描述的逻辑融合的方法。
我不在这里重新发布它的源代码,因为它现在所做的比最初在问题中所寻求的要多得多。
- 简单的ES6承诺问题-交换解决和拒绝参数
- RxJS等待承诺解决
- 如何在解决承诺之前和之后验证值
- AngularJS-我怎么知道何时解决了对父控制器的承诺
- 在我的案例中,如何解决我的承诺问题
- 所有承诺解决后返回
- $.当承诺解决得太早时
- 如果你用另一个承诺解决一个承诺会发生什么
- 基于另一个承诺解决承诺
- 承诺解决不了问题
- 如何知道什么时候所有的承诺都被拒绝了,或者用基本的js承诺解决了
- Ember RSVP承诺解决firefox插件端口消息传递方案无法解决的模型
- 客户端等待服务器承诺解决
- while(true)循环中的承诺/等待承诺解决
- 推迟承诺解决
- 用承诺解决jQuery延迟
- 等待多个单独的承诺解决
- EmberJS - 在承诺解决后调用超级操作
- 如何为另一个承诺解决一个承诺
- 为什么我的承诺散列在传递的承诺解决之前就解决了?