Es gibt kein Problem, das zu erreichen!
Die wichtigste Sache, die Sie beachten müssen, ist, dass Sie die gleiche Objektreferenz (und in Javascript Arrays sind Objekte) in Ihrem Dienst halten müssen.
hier ist unser einfaches HTML:
<div ng-controller = "companiesCtrl">
<ul ng-repeat="company in companies">
<li>{{company}}</li>
</ul>
</div>
Hier unsere Service-Implementierung ist:
serviceDataCaching.service('companiesSrv', ['$timeout', function($timeout){
var self = this;
var httpResult = [
'company 1',
'company 2',
'company 3'
];
this.companies = ['preloaded company'];
this.getCompanies = function() {
// we simulate an async operation
return $timeout(function(){
// keep the array object reference!!
self.companies.splice(0, self.companies.length);
// if you use the following code:
// self.companies = [];
// the controller will loose the reference to the array object as we are creating an new one
// as a result it will no longer get the changes made here!
for(var i=0; i< httpResult.length; i++){
self.companies.push(httpResult[i]);
}
return self.companies;
}, 3000);
}}]);
Und schließlich die Steuerung wie man es wollte:
serviceDataCaching.controller('companiesCtrl', function ($scope, companiesSrv) {
$scope.companies = companiesSrv.companies;
companiesSrv.getCompanies();
});
Erläuterungen
Wie oben gesagt, besteht der Trick darin, den Bezug zwischen dem Dienst und dem Controller beizubehalten. Sobald Sie dies respektieren, können Sie Ihren Controller-Bereich vollständig an eine öffentliche Eigenschaft Ihres Service binden.
Here a fiddle that wraps it up.
In den Kommentaren des Codes können Sie uncomment das Stück versuchen, das nicht funktioniert, und Sie werden sehen, wie die Steuerung die Referenz verliert. Tatsächlich wird der Controller weiterhin einen Verweis auf das alte Array haben, während der Service den neuen ändern wird.
Eine letzte wichtige Sache: Denken Sie daran, dass $ Timeout ein $ apply() auf dem rootSCope auslöst. Aus diesem Grund erfrischt unser Controller-Umfang "alleine". Ohne es, und wenn Sie versuchen, es mit einem normalen setTimeout() zu ersetzen, werden Sie sehen, dass der Controller die Firmenliste nicht aktualisiert. Um dies zu umgehen können Sie:
- nichts tun, wenn Sie Ihre Daten mit $ http abgerufen wird, wie es ein $ gelten auf Erfolg
- wickeln ruft Sie in einem $ Timeout führen (..., 0);
- inject $ rootSCope im Dienst und rufe $ apply() auf es, wenn die asynchrone Operation
- in der Steuerung einen $ Rahmen hinzufügen erfolgt. $ Apply() auf dem getCompanies() verspricht Erfolg
Hoffe, das hilft!
Auch das ist möglich, es gilt als schlechte Praxis. Ich kann nicht herausfinden, warum Axschech den ursprünglichen Ansatz nicht mag – ABOS
@ABOS Die Idee ist, die Daten (und ihren Zustand) im Dienst zu halten, nicht im Controller. Das ursprüngliche Beispiel, und dies tun beide das Gegenteil. Durch die Zuweisung der Daten zum Bereich des Controllers wird der Status in die Hände des Controllers und nicht in den Dienst gestellt. – Axschech
Ich sehe Ihren Punkt jetzt. Aber was ist der Zweck, Daten im Dienst zu halten, um Daten zu teilen? Ich würde es nicht tun, auch das ist der Fall. Ich würde lieber Daten auf dem Controller speichern und wenn ich Daten teilen/Daten auf den Dienst legen möchte, rufe ich einfach die setSharedData (sharedData) -Methode des Dienstes auf. Dies macht Service-Code mehr testbar und wiederverwendbar – ABOS