Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS Function After Multiple Async Service Calls

I have a REST API that I want to call from an AngularJS service like this:

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

There are other implementation details removed there such as authentication that aren't important. The API is provided by a third party so I can't change it.

GET /api/resources returns something like:

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

GET /api/details/one returns something like:

{ "count": 5 }

I then have a controller where I want to call MyApi.resources(), wait for the results and then for each result, call MyApi.details(resource). When the final call to MyApi.details(resource) completes, I want to run a function to aggregate some results from the set of details, but I can't work out how to trigger this at the end.

My controller currently looks like this:

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

What is the best way to achieve the aggregation at the end?

like image 779
Adam Rodger Avatar asked Dec 19 '14 17:12

Adam Rodger


People also ask

How does angular handle async calls?

Basically, Async/Await works on top of Promise and allows you to write async code in a synchronous manner. It simplifies the code and makes the flow and logic more understandable. Note that because it no longer uses then and catch chaining anymore, you can handle errors by running try/catch.

Is angular sync or async?

A common misconception in Angular development is regarding whether observables are synchronous or asynchronous. A lot of (even experienced Angular developers) think that observables are async, but the truth is that they can be… Both synchronous and asynchronous.

What is difference between async and await in angular?

await can only be used in async functions. It is used for calling an async function and waits for it to resolve or reject. await blocks the execution of the code within the async function in which it is located.


1 Answers

You can use deferred's function $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);        
        });
    }
});
like image 138
Joe Samanek Avatar answered Oct 26 '22 04:10

Joe Samanek