104 votes

AngularJS - attente de la finalisation de plusieurs requêtes de ressources

J'ai une seule usine définie avec ngResource :

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

Je fais de multiples appels à la méthode de requête définie sur cette usine. Les appels peuvent se faire de manière asynchrone, mais je dois attendre que les deux appels soient terminés avant de continuer :

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

Existe-t-il un moyen de faire cela avec les fabriques AngularJS définies avec ngResource, de manière similaire à la fonctionnalité $.when().then() de jQuery ? Je préférerais ne pas ajouter jQuery à mon projet actuel.

199voto

Ben Lesh Points 39290

Vous voudrez utiliser des promesses et $q.all() .

En gros, vous pouvez l'utiliser pour envelopper tous vos appels $resource ou $http, car ils renvoient des promesses.

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

21voto

Je pense qu'une meilleure solution est :

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

13voto

Nick A. Watts Points 68

La solution de Ben Lesh est la meilleure mais elle n'est pas complète. Si vous avez besoin de gérer des conditions d'erreur - et, oui, c'est le cas - alors vous devez utiliser la fonction catch sur l'API de promesse comme ceci :

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

});

Si vous ne définissez pas catch et que toutes vos promesses échouent, alors le then ne s'exécutera jamais et laissera donc probablement votre interface dans un mauvais état.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X