Sign up ×
Stack Overflow is a community of 4.7 million programmers, just like you, helping each other. Join them; it only takes a minute:

I'm working on a mobile app using AngularJS as a framework, currently I have a structure similar to this:

app.config(['$routeProvider', function($routeProvider) {
    $routeProvider
        .when('/', {
            templateUrl : 'pages/home.html',
            controller  : 'homeCtrl'
        })

        .when('/one', {
            templateUrl : 'pages/one.html',
            controller  : 'oneCtrl'
        })

        .when('/two', {
            templateUrl : 'pages/two.html',
            controller  : 'twoCtrl'
        });
}]);

app.controller('homeCtrl', ['$scope', function($scope) {

}]);

app.controller('oneCtrl', ['$scope', function($scope) {

}]);

app.controller('twoCtrl', ['$scope', function($scope) {

}]);

And then I'm displaying the content with an ng-view:

<div class="ng-view></div>

Things are working well but I need to load data from a JSON file to populate all the content of the app. What I want is to make and an AJAX call only once and then pass the data through all my different controllers. In my first attempt, I thought to create a Service with an $http.get() inside of it and include that in every controller, but it does not work because it makes a different ajax request everytime I inject and use the service. Since I'm new using angular I'm wondering what is the best way or the more "angular way" to achieve this without messing it up.

Edit: I'm adding the code of the service, which is just a simple $http.get request:

app.service('Data', ['$http', function($http) {
    this.get = function() {
        $http.get('data.json')
        .success(function(result) {
            return result;
        })
    }
});
share|improve this question
2  
Your service is missing from the example code, which would be the most useful thing to see here. – seanhodges Jun 11 at 15:15
    
@Didier I would suggest you to split the code files into different controllers, and use a service for this data fetch. see my answer for service code – Gurbakhshish Singh Jun 11 at 15:44

2 Answers 2

up vote 1 down vote accepted

Try this to get JSON Data from a GET Link:

(function (app) {
    'use strict';

    app.factory('myService', MyService);

    MyService.$inject = ['$q', '$http'];

    function MyService($q, $http) {
        var data;

        var service = {
            getData: getData
        };

        return service;

        //////////////////////////////////////

        function getData(refresh) {
            if (refresh || !data) {
                return $http.get('your_source').then(function(data){
                    this.data = data;
                    return data;
                })
            }
            else {
                var deferrer = $q.defer();
                deferrer.resolve(data);
                return deferrer.promise;
            }
        }
    }

}(angular.module('app')));

Now you can add this dependency in your controller file and use:

myService.getData().then(function(data){
    //use data here 
}, function(err){
    //Handle error here
});
share|improve this answer
    
This worked like a charm, I thougth to solve this problem in several ways but using a singleton pattern never crossed my mind. Thanks! – Didier Jun 11 at 17:08
    
I'm getting this is undefined for the line this.data = data; , and if I remove it then the GET request happens multiple times. Any idea? – bjesus Aug 29 at 18:37
    
initializing a new promise is not needed as $http returns a promise, you can return a reference to the promise instead, the answer is correct but it can be more concise – Dane Macaulay Nov 13 at 2:42

Initialize the promise once, and return a reference to it:

No need to initialize another promise. $http returns one.

Just tack a .then() call on your promise to modify the result

angular.module('app', [])
  .service('service', function($http){
    this.promise = null;
    function makeRequest() {
         return $http.get('http://jsonplaceholder.typicode.com/posts/1')
             .then(function(resp){
                  return resp.data;
             });
    }
    this.getPromise = function(update){
      if (update || !this.promise) {
         this.promise = makeRequest();
      }
      return this.promise;      
    }
  })

Codepen example

share|improve this answer
    
This works fine if you don't need to modify/treat the data returned by the get response since this return the promise itself instead of the data, unfortunatelly it was not my case. Thanks for reply. – Didier Jun 11 at 17:07
    
the example can be extended to do that :) – Dane Macaulay Jun 11 at 19:06
    
Yes It can be extended, indeed this is a very good answer the only reason I didn't choose it as the "accepted answer" was because haw-i-'s answer already considered the fact the data could be treated. Thanks a lot, again. – Didier Jun 15 at 17:42
    
I up-voted this answer because @DaneMacaulay went the extra mile and demonstrated the idea with a codepen example. Very clean and efficient approach. – Rod Hartzell Nov 12 at 18:51

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.