AngularJS - Warten Sie, bis mehrere Ressourcenabfragen abgeschlossen sind

105

Ich habe eine einzelne Factory mit ngResource definiert:

App.factory('Account', function($resource) {
    return $resource('url', {}, {
        query: { method: 'GET' }
    });
});

Ich rufe die in dieser Factory definierte Abfragemethode mehrfach auf. Die Anrufe können asynchron erfolgen, aber ich muss warten, bis beide Anrufe abgeschlossen sind, bevor ich fortfahre:

App.controller('AccountsCtrl', function ($scope, Account) {
    $scope.loadAccounts = function () {
        var billingAccounts = Account.query({ type: 'billing' });
        var shippingAccounts = Account.query({ type: 'shipping' });

        // wait for both calls to complete before returning
    };
});

Gibt es eine Möglichkeit, dies mit AngularJS-Fabriken zu tun, die mit ngResource definiert wurden, ähnlich wie die $ .when (). Then () -Funktionalität von jQuery? Ich würde es vorziehen, meinem aktuellen Projekt kein jQuery hinzuzufügen.

Nathan Donze
quelle

Antworten:

200

Sie sollten Versprechen und $ q.all () verwenden .

Grundsätzlich können Sie damit alle Ihre $ resource- oder $ http-Aufrufe einschließen, da sie Versprechen zurückgeben.

function doQuery(type) {
   var d = $q.defer();
   var result = Account.query({ type: type }, function() {
        d.resolve(result);
   });
   return d.promise;
}

$q.all([
   doQuery('billing'),
   doQuery('shipping')
]).then(function(data) {
   var billingAccounts = data[0];
   var shippingAccounts = data[1];

   //TODO: something...
});
Ben Lesh
quelle
17
Ressourcen geben keine Versprechen zurück, sondern Objekte, die in Zukunft gefüllt werden sollen. In der instabilen Version 1.1.3 verfügen Ressourcen jedoch auch über $thenEigenschaften, legen jedoch kein Versprechungsobjekt offen. $promiseVollständige Belichtung wäre in 1.1.4
Umur Kontacı
@ UmurKontacı Dies ist leider nicht in Winkel 1.1.4!
nh2
Details zu den Ressourcen sind keine Versprechen Problem finden Sie in diesem Thread und in dieser Pull-Anfrage .
nh2
1
Diese Antwort zeigt, wie man es schreibt, sobald es implementiert ist.
nh2
3
Ihre Antwort ist sehr hilfreich und ich glaube, es ist der sinnvollste Weg, Ressourcen in Versprechungen im aktuellen Winkel umzuwandeln. Es kann hilfreich sein, hinzuzufügen, dass in der Dokumentation von $q, mit der Sie verlinkt haben, garantiert wird, dass das Ergebnisarray in derselben Reihenfolge wie das Versprechungsarray liegt.
nh2
20

Ich denke, eine bessere Lösung ist:

$q.all([
   Account.query({ type: 'billing' }).$promise,
   Account.query({ type: 'shipping' }).$promise
]).then(function(data) {
   var billingAccounts = data[0];
   var shippingAccounts = data[1];

   //TODO: something...
});
Geschichten Mundim Andrade Porto
quelle
1
Für mich hat am Ende ohne $ Versprechen gearbeitet ... Genau wie: Account.query ({Typ: 'Abrechnung'}), Account.query ({Typ: 'Versand'})
Georgeos
12

Die Lösung von Ben Lesh ist die beste, aber nicht vollständig. Wenn Sie mit Fehlerbedingungen umgehen müssen - und ja, das tun Sie -, müssen Sie die catchMethode für die Versprechen-API wie folgt verwenden:

$q.all([
   doQuery('billing'),
   doQuery('shipping')
]).then(function(data) {
   var billingAccounts = data[0];
   var shippingAccounts = data[1];

   //TODO: something...

}).catch(function(data) {

   //TODO: handle the error conditions...

}).finally(function () {

  //TODO: do final clean up work, etc...

});

Wenn Sie nicht definieren catchund alle Ihre Versprechen fehlschlagen, wird die thenMethode niemals ausgeführt und Ihre Schnittstelle wird wahrscheinlich in einem schlechten Zustand sein.

Nick A. Watts
quelle