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?
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.
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.
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.
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);
});
}
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With