[英]Make $q.all fail silently when one promise is rejected
我正在對一些地址進行地理編碼,有時其中一些地址失敗。 我希望能夠得到剩下的結果並忽略失敗的結果,這樣我就可以在地圖上顯示其他坐標。 目前$ q.all將在拒絕一個時調用errorHandler,因此我將丟失其他promise的結果。
$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);
});
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
}
});
你想要的是q.allSettled
,它沒有在Angular中實現。
這是一個請求其實現的相關GitHub問題 。
這里有一個可能的實現 ,名為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;
}]);
})
;
您可以僅使用Angular的實現來解決您的問題,您必須做的是隔離其他函數中的異步調用,該函數將返回一個承諾,並且將為您管理此承諾。
讓我們舉一個例子,假設您有四個異步調用,並且每個函數都使用授權控制調用一個端點,如果用戶沒有所有權限,則調用將失敗
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服務並管理一旦調用后將如何返回promise失敗或成功,對於這個例子,讓我們調用該函數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想要的,唯一的區別是如果服務失敗我們返回一個空數組。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.