0

I've created a service that fetches data from the server. The browser tools confirm that the data is picked up correctly.

angular.
  module('karassApp').
  factory('Person', ['$rootScope', '$http', function($rootScope, $http){

    var persons = [];
    var loaded = false;

    // returns a promise that resolves to the persons. 
    var load = function(){
      return $http.get('/get_persons').then(function(response){
        persons = response.data.map(function(person){
          return {
            id: person.id,
            fullname: person.fullname, 
            birthdate: person.birthdate ? new Date(person.birthdate) : null,
            deathdate: person.deathdate ? new Date(person.deathdate) : null,
            description: person.description,
            picture: person.picture ? person.picture : '/client/views/person.png'
          };
        });

        $rootScope.$broadcast('Persons.update');
        loaded = true;

        return persons;
      });
    };

    return {
      load: load,
      persons: persons
    };
  }]);

Next up, I have controller that's supposed to be consuming the service.

angular.
  module('karassApp').
  component('personList', {
    templateUrl: 'client/views/person-list.template.html',
    controller: ['$scope', 'Person', function PersonListController($scope, Person){
      var self = this;

      Person.load().then(function(){
        $scope.persons = Person.persons;
      });
...

At this point, the code fails and $scope.persons ends up empty. I waiting for the person promise to resolve should ensure that the data is loaded into persons. I also thought that the service was a singleton, which means the persons variable should be filled after the first call to Person.load().

Thanks in advance, Josh

Update I tried to incorporate the code from the answer, and it looks like this now:

angular.
  module('karassApp').
  factory('Person', ['$http', '$q', function($http, $q){

    var persons = [];

    // returns a promise that resolves to the persons. 
    var load = function(){
      return $q(function(resolve, reject){
        $http.get('/get_persons').then(function(response){
          persons = response.data.map(function(person){
            return {
              id: person.id,
              fullname: person.fullname, 
              birthdate: person.birthdate ? new Date(person.birthdate) : null,
              deathdate: person.deathdate ? new Date(person.deathdate) : null,
              description: person.description,
              picture: person.picture ? person.picture : '/client/views/person.png'
            };
          });
          resolve(persons);
        });
      });
    };

...

Joshua M. Moore
  • 381
  • 6
  • 20
  • I tried your code, but unfortunately it still didn't work. – Joshua M. Moore Sep 23 '17 at 21:05
  • The update is a [deferred anti-pattern](https://stackoverflow.com/questions/30750207/is-this-a-deferred-antipattern) and should be avoided. As written, the promise it creates hangs if the $http request fails. The error case is not handled properly. – georgeawg Sep 26 '17 at 00:36

1 Answers1

1

I figured it out. I had the right idea, but I needed to return persons to be able to pass it to the next then.

service:

angular.
  module('karassApp').
  factory('Person', ['$rootScope', '$http', '$q', function($rootScope, $http, $q){

    var persons = [];

    // returns a promise that resolves to the persons. 
    var load = function(){
      return $http.get('/get_persons').then(function(response){
        persons = response.data.map(function(person){
          return {
            id: person.id,
            fullname: person.fullname, 
            birthdate: person.birthdate ? new Date(person.birthdate) : null,
            deathdate: person.deathdate ? new Date(person.deathdate) : null,
            description: person.description,
            picture: person.picture ? person.picture : '/client/views/person.png'
          };
        });
        return persons;
      });
    };

controller:

angular.
  module('karassApp').
  component('personList', {
    templateUrl: 'client/views/person-list.template.html',
    controller: ['$scope', 'Person', function PersonListController($scope, Person){
      var self = this;

      Person.load().then(function(persons){
        self.persons = persons;
      });
Joshua M. Moore
  • 381
  • 6
  • 20
  • This is the correct answer. The problem was that the callback function in the `.then` method omitted an argument which you corrected to be `persons`. – georgeawg Sep 26 '17 at 00:38