Skip to content Skip to sidebar Skip to footer

Trouble With Asynchronous Events In Angular

The code I have loops through 10 items in an array, makes a request for each item, then pushes the returned data to an array. Everything runs fine until the $q.all line. details.ge

Solution 1:

This is a pretty common error when dealing with async in javascript.

The question should should ask is: "when the resolver (the function you pass to .then) looks up the variable deferred, what variable does it get back?". Then answer is, they all reference the very last deferred you declare.

The problem is, you're declaring deferred outside of your resolve function. Remember how javascript looks up variables:

  1. Is the variable (in our case, deferred) available in the immediate function scope? (in our case, no)
  2. Traverse up parent scopes until we find a variable with the given name.

By the time the resolver fires, you've redeclared deferred 10 times, each declaration overwriting the previous one! So each time a resolver fires, it actually resolves the same deferred!

The answer is to wrap your deferred declaration in a closure:

for(var i=0; i<page.length; i++){
  (function(){
    var deferred = $q.defer();
    ngGPlacesAPI.placeDetails({placeId: page[i][i]})
      .then(function(data){
        combinedItems.push(data);
        console.log(combinedItems); /// This shows the objects being pushed into the array
        deferred.resolve();
      });
    promises.push(deferred.promise);
  })()
}

But really, you can simplify your whole program and avoid the deferreds. Let me know if this makes sense to you!:

details.getDetails = function(idSet, pageNum) {
  var page = idSet[pageNum];

  // generate an array from 0 to page.length
  var items = Array.apply(null, { length: page.length })

  var promises = items.map(function (i) {
    return ngGPlacesAPI.placeDetails({placeId: page[i][i]});
  })

  return $q.all(promises)
};

Post a Comment for "Trouble With Asynchronous Events In Angular"