2016-05-31 155 views
5

我對angular2相當陌生,我有點卡在某物上。Angular2全局變量可觀察

我創建了一個全局的settings.service。此服務從API獲取設置並使用收集的數據填充設置模型。

服務:

public settings : settingsModel; 

constructor(public http: Http){ 
    this.setSettings() 
     .subscribe(
      (data) => { 
        this.settings = data 
      }); 
    } 

setSettings() : Observable<any>{ 
    return : this.http.get('/settings') 
      .map(response => response.json()); 
} 

getSettings(){ 
    return this.settings; 
} 

這工作得很好,當我在.MAP測試返回數據的設置正確

但是,當我嘗試從我需要組件調用的getSettings這個數據,它返回空。該服務在引導程序中定義。

我是否需要使'settings'變量可觀察?任何幫助將不勝感激!

Tnx!

+0

似乎你的實際代碼是不同的。 '在我測試.map'中的返回數據時正確設置。此代碼'this.http.get('/ settings') .map(response => { this.settings = response.json() });'永遠不會執行''subscribe(...)' –

+0

是的,我的實際代碼是不同的;)但爲了這個問題,我簡化了代碼。我將更新代碼示例;) – Jeffrey

回答

2

我會實現緩存到使用do運營商服務:

private settings : settingsModel; 

constructor(public http: Http){ 
    this.settingsObservable = this.http.get('/settings') 
     .map(response => response.json()) 
     .do(settings => { 
      this.settings = settings; 
     }).share(); 
} 

getSettings() { 
    if (this.settings) { 
    return Observable.of(this.settings); 
    } else { 
    return this.settingsObservable; 
    } 
} 
+1

如果使用BehaviorSubject,則不必「共享()」或緩存。如果感興趣,請查看我的答案 –

0

爲什麼你不使用你的服務是這樣的: -

public settings : settingsModel; 

constructor(public http: Http){ } 

GetSettings(){ 
    return this.http.get('/settings') 
    .map(response => { 
      this.settings = response.json() // here setting your data to `this.setting` 
      return this.settings; 
     }) 
     .catch(err => { 
      console.log(err) // handle your error as you want to handle 
     }) 
} 

,比使用.subscribe()方法要得到數據和視圖上顯示

+0

我已經這樣做了,但我試圖減少API調用的數量。由於數據不會改變,或者只是由客戶端自己修改,所以不需要每次調用「新」數據。 – Jeffrey

+0

沒問題,你可以使用@thierry在他的回答中使用'observable'建議使用 –

7

在您的服務中使用BehaviorSubject。這已經是共享的,它會給新用戶的當前值(它確實是這樣的緩存你):

import {Injectable}  from '@angular/core'; 
import {Http}   from '@angular/http'; 
import {BehaviorSubject} from 'rxjs/BehaviorSubject'; 
import {settingsModel} from 'settingsModel'; 

@Injectable() 
export class MyService { 
    private _settingsSource = new BehaviorSubject<settingsModel>(null); 
    settings$ = this._settingsSource.asObservable(); 
    constructor(private _http:Http) { 
    this._http.get('./settings.json') 
     .subscribe(response => { 
     //console.log('response', response) 
     this._settingsSource.next(response.json()) 
     }); 
    } 
} 

然後使用可觀察到的在您的模板與asyncPipe,或將數據提取到一個組分變量:

this.settings$ = this._myService.settings$; // use with asyncPipe 
this._myService.settings$.subscribe(data => this.settings = data); 

Plunker

在Plunker我有等待4秒鐘,然後再01子組件s,以顯示確實檢索到最新/當前值。 Plunker還演示了asyncPipe的使用。

+0

儘管我喜歡將BehaviorSubject用於全局數據的想法,但是在處理任何實際數據之前發出的初始值時遇到困難。在我的情況下,我需要基於BehaviorSubject的值獲取組件中的其他數據,如果它包含空值,則失敗。任何想法如何解決這個問題? – Liquinaut

+0

解決了我的問題。對於任何正在尋找解決方案的用戶,可以使用ReplaySubject而不是BehaviorSubject來獲取發佈更改而不具有初始值的Subject。在第一次調用next()之前,ReplaySubject不會發出任何數據。 – Liquinaut

+0

@Mark Rajcok - 你爲什麼要等4秒?如何等待他的初始價值? –