我有一个带有这种异步API的AngularJS服务:
myService.asyncCall(['id0', 'id3', 'id2']).then(function (complexData) {
// handle complexData
}).catch(function (error) {
console.log(error);
});
asyncCall
包含由$http
处理的多个$q.all
来电。每个$http
请求都可以响应错误,我希望错误由一个catch
处理程序处理。那么我怎样才能实现catch
处理程序的多次调用?
答案 0 :(得分:5)
如果我理解正确(最后),这就是你想要实现的目标:
$q.all
应该是"扩充"为了满足您的需求,因为默认情况下:
这是一个可能的实现:
function asyncCall(listOfPromises, onErrorCallback, finalCallback) {
listOfPromises = listOfPromises || [];
onErrorCallback = onErrorCallback || angular.noop;
finalCallback = finalCallback || angular.noop;
// Create a new list of promises that can "recover" from rejection
var newListOfPromises = listOfPromises.map(function (promise) {
return promise.catch(function (reason) {
// First call the `onErrroCallback`
onErrorCallback(reason);
// Change the returned value to indicate that it was rejected
// Based on the type of `reason` you might need to change this
// (e.g. if `reason` is an object, add a `rejected` property)
return 'rejected:' + reason;
});
});
// Finally, we create a "collective" promise that calls `finalCallback` when resolved.
// Thanks to our modifications, it will never get rejected !
$q.all(newListOfPromises).then(finalCallback);
}
另请参阅此 short demo 。
答案 1 :(得分:1)
一种方法是将.catch
处理程序单独附加到您的服务中:
function asyncCall(urls){
var calls = urls.map(makeSomeCall).
map(function(prom){ return prom.catch(e){ /* recover here */});
return $q.all(calls);
};
另一种方法是实现类似settle
的{{1}}方法,但会跟踪所有结果。从我的回答中窃取here:
$q.all
你可以处理多个承诺:
function settle(promises){
var d = $q.defer();
var counter = 0;
var results = Array(promises.length);
promises.forEach(function(p,i){
p.then(function(v){ // add as fulfilled
results[i] = {state:"fulfilled", promise : p, value: v};
}).catch(function(r){ // add as rejected
results[i] = {state:"rejected", promise : p, reason: r};
}).finally(function(){ // when any promises resolved or failed
counter++; // notify the counter
if (counter === promises.length) {
d.resolve(results); // resolve the deferred.
}
});
});
})
这使您可以访问承诺的所有结果,无论它是否失败,并让您以更细的粒度进行恢复。
您的服务应该处理该聚合,因为它是对所有内容返回承诺的聚合。一个例子是:
var promiseArr = ["id0","id3","id2"].map(makePromise);
settle(promiseArr).then(function(results){
var failed = results.filter(function(r){ return r.state === "rejected"; });
var failedValues = failed.map(function(i){ return i.value; });
var done = results.filter(function(r){ return r.state === "fulfilled"; });
var doneValues = done.map(function(i){ return i.value; });
});