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


105

我有一个用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添加到当前项目中。

Answers:


200

您将要使用promise和$ q.all()

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

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
资源不返回承诺,它们返回将来要填充的对象。但是,在不稳定的 1.1.3版本中,资源也具有$then属性,但不公开任何promise对象。$promise完全暴露在1.1.4中
UmurKontacı13

不幸的是,@UmurKontacı这不是在1.1.4版本中!
nh2

可以在此线程此pull请求中找到有关资源的详细信息,而不是诺言问题
nh2

1
该答案说明了一旦实现,如何编写。
nh2

3
您的回答非常有帮助,我相信这是将资源转换为当前角度的承诺的最明智的方法。在$q链接到的文档中添加它可能会有所帮助,它可以确保结果数组与promise数组的顺序相同。
nh2

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

1
对我来说,最后没有$ promise就工作了……就像:Account.query({type:'billing'}),Account.query({type:'shipping'})
georgeos

12

Ben Lesh的解决方案是最好的,但还不完整。如果您需要处理错误情况-是的,那么您必须-例如,必须catch在promise 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方法将永远不会执行,因此可能会使您的接口处于错误状态。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.