Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS App: Load data from JSON once and use it in several controllers

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;
        })
    }
});
like image 927
Didier Avatar asked Jun 11 '15 15:06

Didier


2 Answers

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

Edit: you may consider using $http cache instead. It can achieve the same results. From the docs:

If multiple identical requests are made using the same cache, which is not yet populated, one request will be made to the server and remaining requests will return the same response.

like image 192
Dane Macaulay Avatar answered Oct 30 '22 01:10

Dane Macaulay


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
});
like image 44
Gurbakhshish Singh Avatar answered Oct 29 '22 23:10

Gurbakhshish Singh