webentwicklung-frage-antwort-db.com.de

Was passiert mit $ q.all (), wenn einige Aufrufe funktionieren und andere fehlschlagen?

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?

62
Alan2

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 Qhttps://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.

39
Chandermani

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
            }
        }
    }
);
38
Vexter

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;
        }
    });
});
6
Maruf

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
});

http://jsfiddle.net/wd9w0ja4/

5
user3232739

Ich habe ein neues Paket angular gefunden, das die allSettled-Funktionalität in angle zu $ ​​q hinzufügt:

https://github.com/ohjames/angular-promise-extras

4
birdy1980

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.

1
toxaq

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:

  1. Jedes implementierte Versprechen/Anruf schlägt auch einen Rückruf fehl, wobei die "Umleitungs" -Funktion sowohl bei erfolgreichen als auch bei fehlgeschlagenen Rückrufen aufgerufen wird.
  2. In dieser Funktion wird der Zähler gesetzt, der bei jedem Aufruf erhöht wird. Wenn die Anzahl der Versprechungen/Anrufe erreicht ist, wird zur nächsten Ansicht weitergeleitet.

Ich weiß, dass es ziemlich lahm ist, es zu tun, aber es hat bei mir funktioniert.

0
Diomos