Reading data from JSON file in Angularjs using a Promise

Renaud is Not Bill Gates picture Renaud is Not Bill Gates · Dec 12, 2015 · Viewed 7.3k times · Source

I have a factory which provides me a promise when getting a json file :

myapp.factory('topAuthorsFactory', function($http, $q) {
    var factory = {
        topAuthorsList: false,
        getList: function() {
            var deffered = $q.defer();
            $http.get('../../data/top_10_authors.json')
                .success(function(data, status) {
                    factory.topAuthorsList = data;
                }).error(function(data, status) {
                    deffered.reject('There was an error getting data');
                });
            return deffered.promise;
        }
    };
    return factory;
});

and in my controller I want to display the content of the json file on my console as the following :

myapp.controller('topAuthorsController', function($scope, topAuthorsFactory) {


  $scope.listAuthors = topAuthorsFactory.getList().then(function(topAuthorsList) {

      $scope.listAuthors = topAuthorsList;
      console.log('Testing...');

  }, function(msg) {
    alert(msg);
  });

  console.log($scope.listAuthors);
    }

but in my console I'm getting this :

enter image description here

so how can I solve this ? and why I dont see the message "testing..." in console ?

Answer

Pankaj Parkar picture Pankaj Parkar · Dec 12, 2015

You should resolve promise when you received response.

deferred.resolve(data)

Ideally you shouldn't follow the approach by which you are doing, creating new promise is considered as anti-pattern while you are dealing with $http.get which already return promise itself, you could utilize that promise. So basically you need to clean up your factory. By returning the $http.get object & .then function over it, (also .success & .error methods are deprecated). 1st function of then will get call when data received & otherwise the error function will get call. Basically for resolving or rejection promise you need to return data from promise, which will call subsequent .then function of caller method.

Factory

myapp.factory('topAuthorsFactory', function($http) {
  var factory = {
    topAuthorsList: false,
    getList: function() {
      //returning promise
      return $http.get('../../data/top_10_authors.json')
        .then(function(response) {
           var data = response.data;
           factory.topAuthorsList = data;
           //returning data to resolving promise
           return data;
        }, function(error) {
            return 'There was an error getting data';
        });
    }
  };
  return factory;
});

Edit

Basically you have assigned factory method call topAuthorsFactory.getList() to $scope.listAuthors method which is not required here, and then you are printing $scope.listAuthors variable which will obviously have promise object. So you should remove that assignment, & $scope.listAuthors value will be assigned from the .then function.

Controller

//remove $scope.listAuthors assignment which is incorrect.
topAuthorsFactory.getList().then(function(topAuthorsList) {
   $scope.listAuthors = topAuthorsList;
   console.log('Testing...');

}, function(msg) {
    alert(msg);
});

its asynchronous which will evaluate its function when async call get completed..the console.log statement