AngularJS函数在多次异步服务调用后

AngularJS Function After Multiple Async Service Calls

本文关键字:服务 调用 异步 函数 AngularJS      更新时间:2023-09-26

我有一个REST API,我想从AngularJS服务调用它,如下所示:

angular.module('myModule').service('MyApi', ['$http', function($http) {
    return ({
        resources: resources,
        details: details
    });
    function resources() {
        return $http.jsonp('/api/resources');
    }
    function details(key) {
        return $http.jsonp('/api/details/' + id);
    }
}]);

那里删除了其他实现详细信息,例如不重要的身份验证。该 API 由第三方提供,因此我无法更改它。

GET /api/resources返回如下内容:

[{ "key": "one" }, { "key": "two" }]

GET /api/details/one返回如下内容:

{ "count": 5 }

然后我有一个控制器,我想在其中调用MyApi.resources(),等待结果,然后对于每个结果,调用MyApi.details(resource)。当对MyApi.details(resource)的最终调用完成时,我想运行一个函数来聚合一组详细信息中的一些结果,但我无法弄清楚如何在最后触发它。

我的控制器当前如下所示:

angular.module('myModule').controller('MyCtrl', ['$scope', 'MyApi', function($scope, MyApi) {
    $scope.results = new Array();
    MyApi.resources().then(function(response) {
        var resources = response.data;
        var length = resources.length;
        for (var i = 0; i < length; i++) {
            MyApi.details(resources[i].key).then(function(response) {
                $scope.results.push(response.data.count);
            });
        }
    });
    // how do I get this line to run only after all the results are returned?
    $scope.total = $scope.results.reduce(function(a, b) { return a + b; }, 0);
}]);

最后实现聚合的最佳方法是什么?

您可以使用 deferred 的函数 $q.all

angular.module('myModule').controller('MyCtrl', ['$scope', 'MyApi', '$q', function($scope, MyApi, $q) {
    $scope.results = new Array();
    MyApi.resources().then(function(response) {
        var resources = response.data;
        var length = resources.length;
        var defer = $q.defer();
        var promises = [];
        angular.forEach(resources, function(value) {
            promises.push(MyApi.details(resources[i].key));
        });
        $q.all(promises).then(function() {
            $scope.total = $scope.results.reduce(function(a, b) { return a + b; }, 0);        
        });
    }
});

两种方式:

  • $q服务

    使用 $q.all(( 和你所有的详细信息承诺

  • 承诺链

    仅当上一个详细信息已解决时,才调用下一个详细信息

在你的第一个 .then 中,创建一个承诺并将循环中的所有请求链接起来,然后返回它。然后,您可以使用 .then 在代码完成后运行代码。

angular.module('myModule').controller('MyCtrl', ['$scope', 'MyApi', function($scope, MyApi) {
    $scope.results = new Array();
    MyApi.resources().then(function(response) {
        var resources = response.data;
        var length = resources.length;
        var promise;
        function getDetails(key) {
            return function () {
                MyApi.details(key).then(function(response) {
                    $scope.results.push(response.data.count);
                })
            };
        }
        for (var i = 0; i < length; i++) {
            if (i === 0) {
                promise = getDetails(resources[i].key)();
            } else {
                promise.then(getDetails(resources[i].key));
            }
        }
        return promise;
    }).then(function () {
        $scope.total = $scope.results.reduce(function(a, b) { return a + b; }, 0);
    });
}]);