AngularJS - 等待多个资源查询完成

Nat*_*nze 104 angularjs

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

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

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

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
    };
});
Run Code Online (Sandbox Code Playgroud)

是否有办法使用ngResource定义的AngularJS工厂,类似于jQuery的$ .when().then()功能?我宁愿不将jQuery添加到我当前的项目中.

Ben*_*esh 198

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

基本上,您可以使用它来包装所有$ resource或$ http调用,因为它们返回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...
});
Run Code Online (Sandbox Code Playgroud)

  • 资源不返回promise,它们返回将来要填充的对象.但是在*unstable*1.1.3版本中,资源也有`$ then`属性,但不暴露任何promise对象.完全公开`$ promise`将在1.1.4中 (17认同)
  • 您的答案非常有用,我相信这是将资源转换为当前角度承诺的最明智的方法.在您链接到的`$ q`文档中添加它可能会有所帮助,它保证结果数组与promise数组的顺序相同. (3认同)

小智 20

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

$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...
});
Run Code Online (Sandbox Code Playgroud)


Nic*_*tts 12

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

});
Run Code Online (Sandbox Code Playgroud)

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