0

I am a newbie at angular and not too strong in javascript to begin with. I'm trying to make an app using ionic framework. And im trying to get a list from a json file. I've successfully made it work with the raw json in a variable. But i'm now trying to use $http.get() to retrieve it from a remote file in my project folder.

.service('staffServices', ['$q', '$http', staffService]);

function staffService($q, $http) {
  var staffs = {};
  var promise = $http.get("/js/jsons/settings.json")
  .success(function(response) {
    staffs = response.staffSettings;
    console.log(staffs);    //HAS WHAT I NEED
  });
  console.log(staffs);      //EMPTY OBJECT


  return {
    loadAllSettings: function () {          
      return $q.when(staffs);          
    },
    query: function (params) {
      return filterFilter(staffs, params);
    },
    get: function (params) {
      return this.query(params)[0];
    }
  }
};

For some reason i can't access the result outside of the .success() function. I'm not sure if this is due to my ignorance in javascript or my newbie status in angular. Please help me out

This is my controller below. self.settings never gets populated and always returns an empty object

.controller("staffCtrl", function (staffServices) {
  var self = this;

  self.settings = [];
  staffServices.loadAllSettings()
  .then(function (settings) {
    self.settings = [].concat(settings);
    console.log(settings);
  });
});
Raymond Ativie
  • 1,747
  • 2
  • 26
  • 50
  • Your code works as expected. The bottom log occurs before the promise is called, so the object is still empty. But your return function should work with the response data correctly (loadAllSettings,query) – Karmacon Jul 21 '15 at 22:07
  • Yes i know. but it doesn't. Nothing gets returned on the controller.. ever. i've updated the question to show my controller also. @karna – Raymond Ativie Jul 21 '15 at 22:20

2 Answers2

1

I believe the problem is how you're handling the $q and the promise, you could try this also:

// Removed irrelevant return functions temporarily
.service('staffServices', ['$q', '$http', staffService]);

function staffService($q, $http) {
    var deferredPromise = $q.defer();
    var staffs = {};
    var promise = $http.get("/js/jsons/settings.json")
    .success(function(response) {
        staffs = response.staffSettings;
        console.log(staffs);
        deferredPromise.resolve(staffs);
    })
    .error(function(){
        deferredPromise.reject();
        console.log('Unsucessful json call');
    });

    return {
        loadAllSettings: function () {
            return deferredPromise.promise;
        }
    }
};

.controller("staffCtrl", function (staffServices) {
    var self = this;
    self.settings = [];
    staffServices.loadAllSettings()
    .then(function (settings) {
        console.log(settings);
        self.settings = [].concat(settings);
    });
});
Walter R
  • 523
  • 1
  • 7
  • 10
  • It worked :) im not sure why. Care to explain? @walter – Raymond Ativie Jul 22 '15 at 09:37
  • Basically you need to save the async call in a deferred promise and return that. After calling the function you will receive that promise and only after the promise is resolved (by a `.resolve()` or a `.reject()` ) the code inside the `.then()` will execute. Actually, I believe you can even get rid of the "promise" variable inside the staffService function and just call the $http.get directly – Walter R Jul 22 '15 at 21:54
0

The $http.get call is asynchronous, so when you call console.log inside of the .success callback, that statment doesn't actually "happen" until the $http.get request has resolved.

The second time you call console.log, outside of the .success statement, the get request has not resolved yet, so staffs is still the same empty variable it was at the beginning.

If this answer doesn't make sense to you, or you are not familiar with asynchronous stuff, might I recommend you check out this question which does a good job of explaining asynchronous calls.

As for the JSON not returning properly, I believe that $q.when (from the loadAllSettings() function) should be returning a promise, when at present it is returning the JSON object staffSettings. To use a .then call on the returned statement, it needs to be a promise. Try setting staffs to just be equal to response, and then retrieving the .staffSettings attribute in the controller.

.controller("staffCtrl", function (staffService) {
  var self = this;

  self.settings = [];
  staffService.loadAllSettings()
  .then(function (settings) {
    self.settings = [].concat(settings.staffSettings);
    console.log(settings);
  });
});
Community
  • 1
  • 1
turner
  • 1,667
  • 2
  • 13
  • 21
  • Thanks for pointinh out the ideas of asyncronous calls. but the function still never returns the json. is there something im supposed to do to run when it finally gets the json?. i've updated the question to show included my controller also @turner – Raymond Ativie Jul 21 '15 at 22:22
  • Just a quick thing to try before I look at other solutions- could you update 'StaffServices' to simply be 'StaffService' in all locations (i.e. in controller and service both) and let me know if that fixes it? Any error messages that you can find along the way would be helpful as well. – turner Jul 21 '15 at 22:30
  • i just tried that same thing. No errors in the console either – Raymond Ativie Jul 21 '15 at 22:37
  • Okay, I updated my answer with another possible solution, let me know how this works and if you get any error messages with it. I have something else you could try if it doesn't. – turner Jul 21 '15 at 22:53