Mac Mac - 6 months ago 33
AngularJS Question

Synchronizing Multiple Angular $http Calls with $q / Error Handling with $q.catch

I am having trouble figuring out proper use of angular's

$q
and Javascript's
promise
api. Then again, I am pretty new to Javascript, and may be making a syntax error.

This question seems similar, but it doesn't seem to be an exact copy...

My service has a method like this (called by my controller):

self.getResources = function() {

let promises = [];

for (let resourceName in $rootScope.resourceNameList) {

promises.push($http({
url : '/' + resourceName,
method : 'GET'
}).then(function (res) {
return { resourceName : res.data};
}));
}
return promises;
};


And my controller passes the returned promise list into angular's
$q.all()
:

let promises = resourceService.getResources();

$q.all(promises).then(function (resultsArray) {

// resultsArray should be an array of elements like:
// [ {cars : [...]}, {coffeePots : [...]}, {motorBoats : [...]} ]
// with size = resourceNameList.length(), correct?

// this log is never called.
console.log(resultsArray);
$scope.resources = resultsArray;
});


Finally, in my HTML, I try to iterate over and display the resources:

.
.
.
<!-- 'cars' is and example, but I am trying to retrieve this data in the same way -->
<tr ng-repeat="item in resources[cars]">
<td>{{item.property1}}</td>
<td>{{item.property2}}</td>
</tr>


The table is not displaying any results.

I can see from the console that the HTTP requests are successful and returning data, so I must be making a mistake with either the
promise
or
$q
apis.

Any suggestions?

Thanks much.

Answer

I know this is probably a non-answer since you've already figured that you actually have a mistake on your input data set, but you should really detect those kinds of problems earlier by adding a .catch on (at least) your root promise so you can immediately see what's actually up.

In your case, this is your root promise (with the catch already attached). I've broken it into newlines for clarity:

let promises = resourceService.getResources();

$q
 .all(promises)

 // unfortunately, .then only gets executed if all of these promises succeed.
 .then(function (resultsArray) {
   console.log(resultsArray);
   $scope.resources = resultsArray;
 })

 // there is a disturbance in the force!
 .catch(function (error) {
    // you can console.log(error) OR
    window.open("https://stackoverflow.com/search?q="+error.message);
 })
 ;

Happy coding! Here's a great read about promises: http://taoofcode.net/promise-anti-patterns/