Was passiert mit $ q.all (), wenn einige Aufrufe funktionieren und andere fehlschlagen?
Ich habe folgenden Code:
var entityIdColumn = $scope.entityType.toLowerCase() + 'Id';
var requests = $scope.grid.data
.filter(function (rowData, i) {
return !angular.equals(rowData, $scope.grid.backup[i]);
})
.map(function (rowData, i) {
var entityId = rowData[entityIdColumn];
return $http.put('/api/' + $scope.entityType + '/' + entityId, rowData);
});
$q.all(requests).then(function (allResponses) {
//if all the requests succeeded, this will be called, and $q.all will get an
//array of all their responses.
console.log(allResponses[0].data);
}, function (error) {
//This will be called if $q.all finds any of the requests erroring.
var abc = error;
var def = 99;
});
Wenn alle $ http-Aufrufe funktionieren, wird das Array allResponses mit Daten gefüllt.
Wenn einer der Fehler auftritt, wird meines Erachtens die zweite Funktion aufgerufen und die Fehlervariable mit Details versehen.
Kann mir jemand erklären, was passiert, wenn einige der Antworten funktionieren und andere fehlschlagen?
Ich glaube, da die Versprechen-Bibliothek auf der Implementierung von Q
basiert, wird der Rückruf mit dem Fehler aufgerufen, sobald das erste Versprechen abgelehnt wird. Es wartet nicht darauf, dass andere Versprechungen gelöst werden. Siehe Dokumentation von Q
https://github.com/kriskowal/q . Für Q.all ist dies das, was erwähnt wird
Die Funktion all gibt ein Versprechen für ein Array von Werten zurück. Wenn dieses Versprechen erfüllt ist, enthält das Array die Erfüllungswerte der ursprünglichen Versprechen in derselben Reihenfolge wie diese Versprechen. Wenn eines der gegebenen Versprechen abgelehnt wird, wird das zurückgesandte Versprechen sofort abgelehnt, ohne auf den Rest des Stapels zu warten.
Es ist schon eine Weile her, dass diese Frage gestellt wurde, aber vielleicht kann meine Antwort noch jemandem helfen. Ich habe ein ähnliches Problem gelöst, indem ich einfach alle Versprechungen gelöst habe, aber mit einer Rückgabe konnte ich später nachsehen, ob Fehler aufgetreten sind. In meinem Beispiel werden einige Bildelemente vorab geladen:
var loadImg = function(imageSrc) {
var deferred = $q.defer();
var img = new Image();
img.onload = function() {
deferred.resolve({
success: true,
imgUrl: imageSrc
});
};
img.onerror = img.onabort = function() {
deferred.resolve({
success: false,
imgUrl: imageSrc
});
};
img.src = imageSrc;
return deferred.promise;
}
Später kann ich sehen, welche fehlerhaft sind:
var promiseList = [];
for (var i = 0; i < myImageList.length; i++) {
promiseList[i] = loadImg(myImageList[i]);
}
$q.all(promiseList).then(
function(results) {
for (var i = 0; i < results.length; i++) {
if (!results[i].success) {
// these are errors
}
}
}
);
Edit: Nur in Kris Kowals Q unterstützt - aber immer noch ein nützlicher Leckerbissen
Wenn Sie alle verarbeiten möchten, ohne sie bei einem Fehler sofort zurückzuweisen, verwenden Sie allSettled
In den Dokumenten heißt es:
Wenn Sie darauf warten möchten, dass alle Versprechen erfüllt oder abgelehnt werden, können Sie allSettled verwenden.
Q.allSettled(promises)
.then(function (results) {
results.forEach(function (result) {
if (result.state === "fulfilled") {
var value = result.value;
} else {
var reason = result.reason;
}
});
});
Hier ist eine kleine Antwort darauf. In dieser Geige können Sie sehen, wie es funktioniert, wenn in einem Versprechen ein Fehler auftritt.
$q.all([test1(), test2()]).then(function() {
// success
}, function() {
// error
});
Ich habe ein neues Paket angular gefunden, das die allSettled-Funktionalität in angle zu $ q hinzufügt:
Könnten Sie die Fehlerbedingung in Ihren $ http-Versprechen nicht einfach behandeln, bevor Sie sie an $ q übergeben? Versprechen sind angekettet, also sollte dies funktionieren:
return $http.put('/api/' + $scope.entityType + '/' + entityId, rowData).then(function(r){return r;}, angular.noop);
Natürlich können Sie das noop in eine beliebige Transformation ändern, aber dies verhindert, dass die Zurückweisung fehlschlägt, wodurch verhindert wird, dass $q.all
Ausfällt.
In meinem Fall musste ich wissen, wann das letzte Versprechen gelöst wurde, egal ob es erfolgreich war oder nicht. $ q.all war keine Option, da es bei einem Ausfall sofort ausfällt. Ich brauchte dies, um sicherzustellen, dass Benutzer umgeleitet werden, egal was passiert, aber nur, wenn alle Daten verarbeitet werden (oder nicht), damit sie auf der nächsten Seite geladen werden können. So endete ich mit diesem:
Ich weiß, dass es ziemlich lahm ist, es zu tun, aber es hat bei mir funktioniert.