AngularJS: attendi il completamento di più query di risorse


105

Ho una singola fabbrica definita con ngResource:

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

Sto effettuando più chiamate al metodo di query definito in questa fabbrica. Le chiamate possono avvenire in modo asincrono, ma è necessario attendere il completamento di entrambe le chiamate prima di continuare:

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

C'è un modo per farlo con le factory AngularJS definite con ngResource, simile alla funzionalità $ .when (). Then () di jQuery? Preferirei non aggiungere jQuery al mio progetto attuale.

Risposte:


200

Ti consigliamo di utilizzare promesse e $ q.all () .

Fondamentalmente, puoi usarlo per avvolgere tutte le tue chiamate $ resource o $ http perché restituiscono promesse.

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
Le risorse non restituiscono promesse, restituiscono oggetti da riempire in futuro. Tuttavia, nella versione unstable 1.1.3, anche le risorse hanno $thenproprietà ma non espongono alcun oggetto promesso. L'esposizione $promisecompleta sarebbe in 1.1.4
Umur Kontacı

@ UmurKontacı Questo purtroppo non è in 1.1.4 angolare!
nh2

I dettagli sulle risorse non sono problemi di promesse possono essere trovati in questo thread e in questa richiesta di pull .
nh2

1
Questa risposta mostra come scriverla una volta implementata.
nh2

3
La tua risposta è molto utile e credo che sia il modo più sensato per convertire le risorse in promesse nell'attuale angolare. Potrebbe essere utile aggiungere che nella documentazione di $q, a cui si è collegati, si garantisce che l'array dei risultati sia nello stesso ordine dell'array promise.
nh2

20

Penso che una soluzione migliore sia:

$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
Per me ha funzionato senza $ promise alla fine ... Proprio come: Account.query ({type: 'billing'}), Account.query ({type: 'shipping'})
georgeos

12

La soluzione di Ben Lesh è la migliore ma non è completa. Se devi gestire le condizioni di errore e, sì, lo fai, devi utilizzare il catchmetodo sull'API Promessa in questo modo:

$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...

});

Se non definisci catche tutte le tue promesse falliscono, il thenmetodo non verrà mai eseguito e quindi probabilmente lascerà la tua interfaccia in un cattivo stato.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.