2015-06-11 5 views
5

Ich bin in einer mobilen App arbeitet AngularJS als Framework, zur Zeit ich eine ähnliche Struktur wie dieses:AngularJS App: Lastdaten von JSON einmal und es in mehrere Controller verwenden

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) { 

}]); 

Und dann ich bin der Inhalt mit einem ng-view Anzeige:

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

Dinge funktionieren gut, aber ich muss die Daten aus einer JSON-Datei laden alle Inhalte der App zu füllen. Was ich will, ist zu machen und ein AJAX Anruf nur einmal und dann die Daten durch alle meine verschiedenen Controller zu übergeben. Bei meinem ersten Versuch dachte ich daran, einen Dienst mit einem $http.get() darin zu erstellen und das in jedem Controller zu integrieren, aber es funktioniert nicht, weil es jedes Mal, wenn ich den Dienst injiziere und benutze, eine andere Ajax-Anfrage macht. Da ich neu mit eckigen bin frage ich mich, was ist der beste Weg oder der mehr "eckige Weg", um dies zu erreichen, ohne es zu vermasseln.

Edit: ich den Code des Dienstes hinzugefügt, die $http.get Anforderung nur eine einfache ist:

app.service('Data', ['$http', function($http) { 
    this.get = function() { 
     $http.get('data.json') 
     .success(function(result) { 
      return result; 
     }) 
    } 
}); 
+2

Ihr Dienst wird aus dem Beispiel fehlt Code, der am nützlichsten wäre, um hier zu sehen. – seanhodges

+0

@Didier Ich würde vorschlagen, dass Sie die Codedateien in verschiedene Controller aufteilen und einen Service für diesen Datenabruf verwenden. Sehen Sie meine Antwort für Service-Code –

Antwort

4

Versuchen Sie, diese JSON Daten aus einer Sammlung Link zu erhalten:

(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'))); 

Jetzt können Sie diese Abhängigkeit in Ihrem Controller-Datei und die Nutzung hinzufügen:

myService.getData().then(function(data){ 
    //use data here 
}, function(err){ 
    //Handle error here 
}); 
+0

Dies funktionierte wie ein Zauber, ich wollte dieses Problem auf verschiedene Arten lösen, aber mit einem Singleton-Muster kam mir nie in den Sinn. Vielen Dank! – Didier

+0

Ich bekomme 'this is undefined' für die Zeile' this.data = data; ', und wenn ich es entferne, dann passiert die GET-Anfrage mehrmals. Irgendeine Idee? – bjesus

+0

Initialisierung eines neuen Versprechens ist nicht erforderlich, da $ http eine Zusage zurückgibt, können Sie stattdessen einen Verweis auf das Versprechen zurückgeben, die Antwort ist korrekt, aber es kann prägnanter sein –

7

das Versprechen einmal initialisieren, und zurück, um es eine Referenz:

Nein muss ein anderes Versprechen initialisieren. $ http gibt eins zurück.

Gerade tack ein .then() Anruf auf Ihrem Versprechen das Ergebnis

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

bearbeiten zu ändern: Sie stattdessen $ http-Cache kann in Betracht ziehen. Es kann die gleichen Ergebnisse erzielen. From the docs:

Wenn mehrere identische Anfragen denselben Cache unter Verwendung gemacht werden, die noch nicht aufgefüllt ist, wird eine Anforderung die gleiche Antwort auf den Server und die verbleibenden Anforderungen vorgenommen werden zurückkehren wird.

+0

Das funktioniert gut, wenn Sie die Daten nicht ändern/behandeln müssen, die von der get-Antwort zurückgegeben werden, da dies das Versprechen selbst anstelle der Daten zurückgibt, leider war es nicht mein Fall. Danke für die Antwort. – Didier

+0

das Beispiel kann erweitert werden, um das zu tun :) –

+0

Ja Es kann erweitert werden, in der Tat ist dies eine sehr gute Antwort der einzige Grund, warum ich es nicht als die "akzeptierte Antwort" gewählt wurde, weil Haw-i-Antwort bereits berücksichtigte die Tatsache, dass die Daten behandelt werden könnten. Nochmals vielen Dank. – Didier