假设我有3个承诺:
这样:C -> B -> A
我希望能够返回已解决的内容,即A,A和B,或A和B以及C.
我显然必须首先解析A,但如果我使用.then()
链接它们,只要其中一个失败,整个链就会失败。
如果我使用.some()
,它需要一个Promise数组作为输入,因此在这种情况下它不起作用,因为承诺不是彼此独立的。
谢谢。
答案 0 :(得分:2)
不需要任何特殊内容,只需then
和catch
(或诺言库中的等效内容)。
让承诺共享一个封闭范围,可以累积中间结果。
var results = {};
return doA().then(function(a) {
results.a = a;
return doB(a);
}).then(function(b) {
results.b = b;
return doC(b);
}).then(function(c) {
results.c = c;
return results;
}).catch(function(error) {
results.error = error;
return results;
});
答案 1 :(得分:1)
对于可重用的方案,这里是一个表驱动的方法,你只需传入一个函数和标签列表,然后一个接一个地调用它们,将前一个结果提供给下一个结果直到一个拒绝。
如果生成的承诺满足,则解析的值是一个对象,其中包含所需标记属性的所有结果。如果任何操作拒绝,则整体承诺将拒绝,拒绝原因将是包含错误和错误之前收集的所有结果的对象:
function processList(list, initialArg) {
var results = {};
return sequence.reduce(function(p, item) {
return p.then(function(arg) {
// run the next item in the list and collect its result
return item.fn(arg).then(function(result) {
results[list[item.tag]] = result;
return result;
});
});
}, Promise.resolve(initialArg)).then(function() {
// return all results
return results;
}, function(err) {
// there was an error, return both the error and the results we have so far
throw {err, results};
});
}
// example usage
var sequence = [{fn: fnA, tag:"a"}, {fn: fnB, tag:"b"}, {fn: fnC, tag:"c"}];
processList(sequence, "whatever").then(function(results) {
// all results here
// results.a, results.b, results.c
}, function(errResults) {
var err = errResults.err;
var partialResults = errResults.results;
});
您还可以将`processList()更改为始终解析并解析包含您可以检查的错误属性的对象。哪种方式取决于您希望如何使用结果。
function processList(list, initialArg) {
var results = {};
return sequence.reduce(function(p, item) {
return p.then(function(arg) {
// run the next item in the list and collect its result
return item.fn(arg).then(function(result) {
results[list[item.tag]] = result;
return result;
});
});
}, Promise.resolve(initialArg)).then(function() {
// return all results
return {err:0, results: results};
}, function(err) {
// there was an error, return both the error and the results we have so far
return {err, results};
});
}
// example usage
var sequence = [{fn: fnA, tag:"a"}, {fn: fnB, tag:"b"}, {fn: fnC, tag:"c"}];
processList(sequence, "whatever").then(function(results) {
// promise always fulfills
// results.err tells you if there was an error or not
// results.a, results.b, results.c contain whatever results completed
});
答案 2 :(得分:0)
由于这些是承诺,你绝对可以同时操纵这三个,但我不认为.some()
会在这里完成工作。
Promise.filter()
有一些错误处理是一种方法:
var pA = asyncOperation();
var pB = pA.then(operationThatDependsOnA);
var pC = pB.then(operationThatDependsOnB);
// map pA, pB, and pC to promises that will resolve to null if their original promise fails
var safePromises = [pA, pB, pC].map(function (p) {
return p.catch(function () { return null; });
});
// filter the results to the ones that succeeded
Promise
.filter(safePromises, function (value) { return value !== null; })
.then(function (results) {
// results contains whichever promises succeeded, in the order A, B, C
console.log(results);
});
另一个选择是使用.reflect()
作为自己捕获错误的替代方法:
var pA = asyncOperation();
var pB = pA.then(operationThatDependsOnA);
var pC = pB.then(operationThatDependsOnB);
Promise
.filter(
[pA, pB, pC].map(function (p) { return p.reflect(); }),
function (inspection) { return inspection.isFulfilled(); }
)
.map(function (inspection) { return inspection.value(); })
.then(function (results) {
// results contains whichever promises succeeded, in the order A, B, C
console.log(results);
});
答案 3 :(得分:0)
不需要任何特殊功能,如果发生故障,您可以先使用故障处理程序以您喜欢的方式处理错误,然后返回下一个承诺,例如;
var p1 = new Promise((resolve,reject) => {
var r = ~~(Math.random()*100);
r > 49 ? resolve(r) : reject(r);
});
var p2 = new Promise((resolve,reject) => {
var r = ~~(Math.random()*100);
r > 49 ? resolve(r) : reject(r);
});
var p3 = new Promise((resolve,reject) => {
var r = ~~(Math.random()*100);
r > 49 ? resolve(r) : reject(r);
});
p1.then(v => {console.log("p1 resolved to " + v);
return p2;},
v => {console.log("p1 rejected by " + v);
return p2;}
)
.then(v => {console.log("p2 resolved to " + v);
return p3;},
v => {console.log("p2 rejected by " + v);
return p3;}
)
.then(v => console.log("p3 resolved to " + v),
v => console.log("p3 rejected by " + v)
);

根据Roamer-1888关于promise依赖关系的评论,如果生成的随机值大于从前一个promise中获得的值,则promise可以如下修改上述代码;
function nextPromise(v){
var r = ~~(Math.random()*100);
return new Promise((resolve, reject) => r > v ? resolve(r) : reject(r));
}
var pA = new Promise((resolve,reject) => {
var r = ~~(Math.random()*100);
r > 49 ? resolve(r) : reject(r);
});
pA.then(v => {console.log("pA resolved to " + v);
return nextPromise(v);},
v => {console.log("pA rejected by " + v);
return nextPromise(v);}
)
.then(v => {console.log("pB resolved to " + v);
return nextPromise(v);},
v => {console.log("pB rejected by " + v);
return nextPromise(v);}
)
.then(v => console.log("pC resolved to " + v),
v => console.log("pC rejected by " + v)
);