0

I'm trying to store data into a location[] array via http request method to a json file.

The problem is my listings controller always contains an empty array.

My Factory

app.factory('listing__data', function($http, $q){
  return {
    locations: '',
    makeRequest: function(url) {
      // Create the deffered object
      var deferred = $q.defer();

      $http.get('/'+url).then(function(resp) {
        deferred.resolve(resp.data);
      });
      return deferred.promise;
    },
    getUrl: function(params) {
      var url = "locations.json";

      if(!this.locations) {
        this.locations = this.makeRequest(url);
      }
      // Return the myObject stored on the service
      return this.locations;
    }
  };
});

My Controller

var listings__controller = app.controller('listings__controller', function($scope, distance__service, listing__data) {
    $scope.locations = [];

    listing__data.getUrl(distance__service.meters).then(function(data) {
    $.each(data.listings, function(i, item) {
          $scope.locations.push(item.location);
          console.log(item.location); // ** Shows Correct Object **
        });
    });
    console.log("How many inside:"+$scope.locations.length); // ** Empty - Shows 0 **
});

I can't seem to figure out why my $scope.locations = [] remains empty

3
  • You fill $scope.locations, and you print the length of $scope.geoLocations. Commented Aug 18, 2014 at 12:59
  • Your listing__data.makeRequest is an example of the Deferred anti-pattern. $http.get already returns a promise, so there's no need for the deferred: return $http.get(...).then(function (resp) { return resp.data; }); Commented Aug 18, 2014 at 13:18
  • @JBNizet excuse the typo, was refactoring the code to paste here Commented Aug 18, 2014 at 13:48

1 Answer 1

2

Even without the typo that JB Nizet mentioned, you will still see 0, because console.log("How many inside:"+$scope.locations.length); gets executed before the callback you pass to listing__data.getUrl(distance__service.meters).then, since the latter is asynchronous.

Remember that when using asynchronous functions, the flow of execution doesn't follow the order of lines of your source code.

promise.then(function () {
    console.log('inside callback');
});
console.log('outside callback');

will print outside callback then inside callback.

Consequently, if your going to use the value you store inside $scope.locations, you have to do it inside the callback.

Sign up to request clarification or add additional context in comments.

6 Comments

The geo locations inside $scope.locations = [] need to be processed by another library. What would be the correct way to store this in the same scope so I can iterate through these values?
The other library doesn't need the data to be attached to the scope. Do all the processing inside the callback, then attach what you want to display to the scope.
I have two controllers feeding off this listing data. First controller lets call this controller_1 lists the locations and allows the user to delete or favourite. The Second controller controller_2 outputs the locations to a map. They both need to be bindable so in controller_1 if i delete an object from that array, it also removes from my map. In this scenario, still everything needs to be done inside that callback you mentioned?
See this fiddle for an example of how you can share promised data between controllers using a service.
If you have further questions about sharing data between controllers, I would suggest posting a new question (or look for already answered questions), since it is another matter entirely. This question was about writing correct asynchronous code.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.