多个异步服务调用后的AngularJS函数

Ada*_*ger 8 javascript rest asynchronous angularjs

我有一个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);
    }
}]);
Run Code Online (Sandbox Code Playgroud)

还有其他实现细节,例如认证不重要.API由第三方提供,因此我无法更改它.

GET /api/resources 返回类似于:

[{ "key": "one" }, { "key": "two" }]
Run Code Online (Sandbox Code Playgroud)

GET /api/details/one 返回类似于:

{ "count": 5 }
Run Code Online (Sandbox Code Playgroud)

然后我有一个控制器,我想调用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);
}]);
Run Code Online (Sandbox Code Playgroud)

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

Joe*_*nek 13

您可以使用延迟函数$ 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);        
        });
    }
});
Run Code Online (Sandbox Code Playgroud)