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.

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

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

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.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.