0

I asked the wrong question yesterday (and got a goodanswer that worked), but am realizing it's not what I needed. I need to be able to retrieve JSON data (preferably once), store it, and access it throughout my service. The challenge I'm having is that all the examples I can find talk about using JSON and passing to the app/controller, whereas in this case I need to get it, check it, and then it dictates what my module/service does.

For instance, I have my App and Controller, and then I have a module such as (this is psuedo-code, not meant to run):

angular.module("myModule")

.service("myService1", function($q, myService2, $http) {
    this.getModel = function() {
        return {
            title: "My Title",
            desc: "My Desc"
            options: function () {
                if (condition A)
                    return "option1";
                else 
                    return "option2";
            }
        };
    };
})
.service("myService2", function($q, $http) {
    this.getCfgInfo = function () {
        var defer = $q.defer();
        $http.get("my/json/url").then(function(response) {
            defer.resolve(response.data);
        });
        return defer.promise;
    };
})

In this example, I'm wanting to get the JSON, and use it within myService1 for both literal values (title, desc) as well as for conditions (condition A within the if).

I know I can do something like this (thanks to Joel for helping yesterday):

service("myService1", function($q, myService2, $http) {
    // get a promise object for the configuration info
    var cfgProm = rtDataMapper.getCfgInfo()
    this.getModel = function() {
        return {
            title: cfgProm.then(function(response) {
                        return response.JSON_NAME;
                    }),

and it works fine as I've got the title mapped back into my model and there is a watch(), but I'm stumped as to how I get, store, and use the JSON within the service itself as a conditional (i.e. if (condition A) where condition A is coming from the JSON. Trying to wrap these in .then() doesn't seem to make sense, or at least I can't figure out how to do it.

I'm new to Angular and am attempting to modify some code that was left to us. I'm guessing I don't need the myService2 just to get the JSON. Can anyone help point me in the right direction? I've spent several hours online but can't seem to find a relevant reference/example.

Thanks

Community
  • 1
  • 1
  • Are you getting the data once then changing it once based on certain values and then it's good for use throughout the app? – m59 Jan 14 '14 at 19:00
  • I'm getting the data once (it's configuration data coming from a DB via REST/JSON) and then using it to return various things from the service. Long story short, I basically need to do the entire service within a .then block, as I don't want the getModel function to return anything until the JSON has been retrieved and used in the logic. – user3192643 Jan 14 '14 at 19:11
  • I think you still missed the point of my question :( Are you just modifying based on conditional data once or do you need to keep changing it for some reason? – m59 Jan 14 '14 at 19:12
  • Sorry. Once. I'm picking up an app that was left by someone else and trying to modify. Right now there is hardcoded stuff in the service code, and that stuff needs to variable based on the JSON returned. So I get it once, use it, and it doesn't change during the session (JSON will change user to user depending on the params I pass in when getting the JSON). Does that answer your question? – user3192643 Jan 14 '14 at 19:15

1 Answers1

0

Live demo (click).

I'm having the service immediately get the data when it is injected (that code will only run once no matter how many times you inject it). That's nice because you won't have to call a function to get the data - it's called for when creating the service.

Your service method that returns that data will need to return the promise of the data, of course, since you aren't guaranteed that it will have come through when you ask for it. You can pass arguments to that method to use to determine your conditions. All you need to do for that is use promise.then in the method and resolve the promise with the modified data. Since that method is returning the promise already, the modification will be updated on the resolve. See all of this below and in the demo.

var app = angular.module('myApp', []);

app.controller('myCtrl', function($scope, myService) {
  myService.getData(15).then(function(data) {
    $scope.myData = data;
  });
});

app.factory('myService', function($q, $timeout) {
  //this code only runs once when you first inject the service
  //get data immediately
  var deferred = $q.defer();

  $timeout(function() { //simulate ajax call
    var data = { //ajax response data
      foo: 15,
      bar: 'Some data!'
    };
    data = modifyData(data, 1);
    deferred.resolve(data);
  }, 500);

  function modifyData(data, fooVal) {
    if (data.foo === fooVal) {
      data.baz = 'Conditional data!'; 
    }
    return data; 
  }

  var myService = {
    //data can be modified when it comes from the server,
    //or any time you call this function
    getData: function(fooVal) {
      if (fooVal) { //if you want to modify the data
        deferred.promise.then(function(data) {
          data = modifyData(data, fooVal);
          deferred.resolve(data);
        });
      }
      return deferred.promise;
    }
  };
  return myService;
});
m59
  • 43,214
  • 14
  • 119
  • 136
  • Thanks, the explanation and code really helps. At the risk of asking a dumb question, can you clarify how I would get and use the data from a second service? For instance, having a second service with a function where it needed to get the data, and then say "if data = bar" then return true, else return false? – user3192643 Jan 14 '14 at 20:39
  • @user3192643 I'm not sure I understand. You get the data the same way. Inject the service and use `myService.getData(conditionStuff).then(function(modifiedData) { //do something with data });` – m59 Jan 14 '14 at 22:28
  • Yeah, figured it out. I was asking the wrong question. What I was trying to do was to load data once before my app started, and then use it throughout the app. Kind of like this (http://stackoverflow.com/questions/16286605/initialize-angularjs-service-with-asynchronous-data). Thanks for the help, I'm new to this and the explanations were very helpful. – user3192643 Jan 14 '14 at 23:28