我正在对一些地址进行地理编码,有时其中一些地址会失败。我希望能够得到剩下的结果并忽略失败的结果,这样我就可以在地图上显示其他坐标。目前$ q.all会在一个被拒绝时调用errorHandler,所以我失去了其他承诺的结果。
$q.all(promises).then(function(coords) {
for (var j = 0;j<coords.length;j+=1) {
//success code
}
}, function(error) {
console.log("Failed",error.type,error.message);
});
答案 0 :(得分:9)
Interrobang建议的解决方案很好(减去错误)但是如果你不喜欢让装饰器影响代码中的每一个承诺,你可以得到类似于allSettled的东西:
var suppress = function(x) { return x.catch(function(){}); }
$q.all(promises.map(suppress)).then(function(coords) {
for (var j = 0; j < coords.length ; j+=1) {
//coords[j] contains the coords on success or is undefined on failure
}
});
答案 1 :(得分:0)
你想要的是q.allSettled
,这在Angular中没有实现。
这是relevant GitHub issue请求其实施。
以下是one possible implementation,名为allComplete
,您可以将其添加到Angular应用中:
angular.module('App.services', ['ngResource'])
.config( function($provide) {
$provide.decorator("$q", ["$delegate", function($delegate) {
var $q = $delegate;
$q.allComplete = function(promises) {
if(!angular.isArray(promises)) {
throw Error("$q.allComplete only accepts an array.");
}
var deferred = $q.defer();
var passed = 0;
var failed = 0;
var responses = [];
angular.forEach(promises, function (promise, index) {
promise
.then( function(result) {
console.info('done', result);
passed++;
responses.push(result);
})
.catch( function(result) {
console.error('err', result);
failed++;
responses.push(result);
})
.finally( function() {
if((passed + failed) == promises.length) {
console.log("COMPLETE: " + "passed = " + passed + ", failed = " + failed);
if(failed > 0) {
deferred.reject(responses);
} else {
deferred.resolve(responses);
}
}
})
;
});
return deferred.promise;
};
return $q;
}]);
})
;
答案 2 :(得分:0)
你可以只使用Angular的实现来解决你的问题,你要做的就是隔离其他函数中的异步调用,这个函数将返回一个promise,这个承诺将由你来管理。
让我们使用一个例子,假设您有四个异步调用,并且每个函数都使用授权控制调用一个端点,如果用户没有调用将失败的所有权限
function getAllCatalogs() {
return $q.all([
$http.get(baseUrl + 'equipment-design/'),
$http.get(baseUrl + 'engines-design/'),
$http.get(baseUrl + 'suspension-design/'),
$http.get(baseUrl + 'artifacts-design/')
]).then(function (data) {
return data;
});
}
由于$ q.all需要所有承诺完成令人满意,如果之前的一个呼叫由于用户没有权限而失败,则整个呼叫将失败,但也许您对呼叫失败时感兴趣返回一个空数组或一个默认对象,所以你必须自己处理这个行为,要实现这一点,你必须创建一个函数,负责调用 $ http.get 服务并管理如何一旦呼叫失败或成功,将返回承诺,对于此示例,我们将该函数称为 getCatalogPromise ,并且在其参数中将是该服务的URL,代码将为:
function getCatalogPromise(url) {
var deferred = $q.defer();
$http.get(url).then(function (response) {
deferred.resolve(response)
}, function () {
deferred.resolve([]);
})
return deferred.promise;
}
function getAllCatalogs() {
return $q.all([
getCatalogPromise(baseUrl + 'equipment-design/'),
getCatalogPromise(baseUrl + 'engines-design/'),
getCatalogPromise(baseUrl + 'suspension-design/'),
getCatalogPromise(baseUrl + 'artifacts-design/')
]).then(function (data) {
return data;
});
}
如果您注意 getCatalogPromise 的代码,那么返回对服务的调用无关紧要,我们的延迟始终将处于解决状态,这就是 $ q .all 想要,唯一的区别是如果服务失败,我们返回一个空数组。