【问题标题】:AngularJS - wait for multiple resource queries to completeAngularJS - 等待多个资源查询完成
【发布时间】:2013-03-08 17:28:29
【问题描述】:

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

【问题讨论】:

    标签: angularjs


    【解决方案1】:

    您需要使用 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...
    });
    

    【讨论】:

    • 资源不返回承诺,它们返回要在未来填充的对象。然而在 unstable 1.1.3 版本中,资源也有$then 属性但不暴露任何promise 对象。完全暴露 $promise 将在 1.1.4
    • @UmurKontacı 不幸的是,这 not 在 angular 1.1.4 中!
    • 关于resources are not promises问题的详细信息可以在this threadthis pull request找到。
    • This answer 展示了实现后如何编写。
    • 您的回答非常有帮助,我相信这是在当前角度将资源转换为承诺的最明智的方式。在您链接到的$q 的文档中添加它可能会有所帮助,它保证结果数组与承诺数组的顺序相同。
    【解决方案2】:

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

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

    【讨论】:

    • 对我来说,最后没有 $promise... 就像:Account.query({ type: 'billing' }), Account.query({ type: 'shipping' })跨度>
    【解决方案3】:

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

    $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 方法将永远不会执行,因此可能会使您的界面处于错误状态。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-03-23
      • 1970-01-01
      • 1970-01-01
      • 2020-03-22
      • 2022-01-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多