2016-05-31 94 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秒?如何等待他的初始价值? –