在使用Angular开发的单页面应用里,有时需要处理这种场景:使用http请求某个数据,数据请求成功后需要把数据更新到多个组件里。也就是说,有多个observer(观察者)对http请求数据返回的Observable订阅。
getDta() {
return this.http.get('/dataUrl').map(res => res.json());
}
let dataObservable = getDta();
let subscriber1 = dataObservable.subscribe(...);
let subscriber2 = dataObservable .subscribe(...);
如果代码类似上面这样写,你会发现http发了两次请求。这明显和我们的设想有出入,我们是希望http请求完后共享请求的数据。
这里分为两种场景:
- 请求的数据是固定不变的,可以考虑把请求的数据缓存起来
请求数据后是要同时更新多个组件,下次需要重新请求再更新相应的组件
缓存共享数据
对于请求数据是固定不变的或者是在一段时间内不会发生修改,可以考虑把数据缓存起来。
示例:
import {Injectable} from '@angular/core';
import {Http, Headers} from '@angular/http';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/observable/of'; //proper way to import the 'of' operator
import 'rxjs/add/operator/share';
import 'rxjs/add/operator/map';
import {Data} from './data';
@Injectable()
export class DataService {
private url:string = 'https://cors-test.appspot.com/test';
private data: Data;
private observable: Observable<any>;
constructor(private http:Http) {}
getData() {
if(this.data) {
//数据已存在,返回数据的Observable
return Observable.of(this.data);
} else if(this.observable) {
//数据还没有返回,正在请求中,返回该请求的observable
return this.observable;
} else {
//还没有发起请求,发起http请求。
this.observable = this.http.get(this.url)
.map(response => {
//数据返回后,此次的observable不再需要,下次访问返回data的Observable
this.observable = null;
if(response.status == 400) {
return "FAILURE";
} else if(response.status == 200) {
this.data = new Data(response.json());
return this.data;
}
})
.share();//使用share(),允许多个订阅获取结果
return this.observable;
}
}
}
多组件共享每次请求的数据
对于每次请求的数据可能会被修改,那么就不适合缓存数据了。
在Rxjs 5.4.0新增了shareReplay()函数,可以使用它来共享http ajax请求的数据
示例
getDta() {
return this.http.get('/dataUrl').map(res => res.json()).shareReplay();
}
let dataObservable = getDta();
参考:https://*.com/questions/36271899/what-is-the-correct-way-to-share-the-result-of-an-angular-2-http-network-call-in