Non c'è alcun problema per raggiungere questo obiettivo!
La cosa principale da tenere a mente è che devi mantenere lo stesso riferimento all'oggetto (e negli array di javascript sono oggetti) nel tuo servizio.
qui è la nostra semplice HTML:
<div ng-controller = "companiesCtrl">
<ul ng-repeat="company in companies">
<li>{{company}}</li>
</ul>
</div>
Qui è la nostra implementazione del servizio:
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);
}}]);
E infine il controller come si voleva:
serviceDataCaching.controller('companiesCtrl', function ($scope, companiesSrv) {
$scope.companies = companiesSrv.companies;
companiesSrv.getCompanies();
});
Spiegazioni
Come detto sopra, il trucco è mantenere il riferimento tra il servizio e il controller. Una volta rispettato questo, è possibile vincolare completamente l'ambito del controller su una proprietà pubblica del servizio.
Here a fiddle that wraps it up.
Nei commenti del codice si può provare a rimuovere il commento il pezzo che non funziona e si vedrà come il regolatore sta perdendo il riferimento. In effetti il controller manterrà un riferimento al vecchio array mentre il servizio cambierà il nuovo.
Un'ultima cosa importante: tenere presente che il timeout $ sta attivando $ apply() sul rootSCope. Questo è il motivo per cui il nostro ambito di controllo si sta aggiornando "da solo". Senza di esso, e se provi a sostituirlo con un normale setTimeout() vedrai che il controller non sta aggiornando l'elenco delle aziende. Per risolvere questo è possibile:
- non fare nulla se i dati vengono recuperati con $ http come chiama un $ applicare in caso di successo
- avvolgervi tradurrà in un $ timeout (..., 0);
- iniettare $ rootSCope nel servizio e chiamare $ applicare() su di esso quando l'operazione asincrona viene eseguita
- nel controller aggiungere un $ ambito. $ Applicare() sulle getCompanies() promettere successo
Spero che questo aiuti!
Anche questo è possibile, è considerato una cattiva pratica. Non riesco a capire perché ad Axschech non piace l'approccio originale – ABOS
@ABOS l'idea è di mantenere i dati (e il loro stato) nel servizio, non nel controller. L'esempio originale e questo entrambi fanno l'opposto. L'assegnazione dei dati all'ambito del controller mette lo stato nelle mani del controllore e non nel servizio. – Axschech
Vedo il tuo punto ora. Ma qual è lo scopo di mantenere i dati in servizio, per condividere i dati? Non lo farei nemmeno in questo caso. Preferirei memorizzare i dati sul controller e se desidero condividere i dati/mettere i dati in servizio, chiamo semplicemente il metodo setSharedData (sharedData) del servizio. Questo rende il codice di servizio più testabile e riutilizzabile – ABOS