AngularJS – espera que várias consultas de resources sejam concluídas

Eu tenho uma única fábrica definida com ngResource:

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

Eu estou fazendo várias chamadas para o método de consulta definido nesta fábrica. As chamadas podem acontecer de forma assíncrona, mas eu preciso esperar que as duas chamadas sejam concluídas antes de continuar:

 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 uma maneira de fazer isso com fábricas AngularJS definidas com ngResource, semelhante à funcionalidade $ .when () then () do jQuery? Eu preferiria não adicionar o jQuery ao meu projeto atual.

Você vai querer usar promises e $ q.all () .

Basicamente, você pode usá-lo para agrupar todas as suas chamadas $ resource ou $ http porque elas retornam promises.

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

Eu acho que uma solução melhor é:

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

A solução de Ben Lesh é a melhor, mas não está completa. Se você precisa lidar com condições de erro – e, sim, você precisa – então você deve usar o método catch na API de promises da seguinte forma:

 $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 você não definir catch e todas as suas promises falharem, o método then nunca será executado e, portanto, provavelmente deixará sua interface em um estado ruim.