106

我有一个用 ngResource 定义的工厂:

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

我正在多次调用此工厂上定义的查询方法。调用可以异步发生,但我需要等待两个调用完成才能继续:

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

有没有办法使用 ngResource 定义的 AngularJS 工厂来做到这一点,类似于 jQuery 的 $.when().then() 功能?我不希望将 jQuery 添加到我当前的项目中。

4

3 回答 3

205

你会想要使用 Promise 和$q.all()

基本上,您可以使用它来包装您的所有 $resource 或 $http 调用,因为它们返回承诺。

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...
});
于 2013-03-08T18:01:18.517 回答
21

我认为更好的解决方案是:

$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...
});
于 2016-08-22T18:44:09.697 回答
13

Ben Lesh 的解决方案是最好的,但并不完整。如果你需要处理错误情况——是的,你需要——那么你必须使用catchpromise API 上的方法,如下所示:

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

});

如果您没有定义catch并且所有的承诺都失败了,那么该then方法将永远不会执行,因此可能会使您的界面处于不良状态。

于 2016-12-09T14:54:32.867 回答