@H_301_8@
1.此答案https://stackoverflow.com/a/36417240/1063354使用私有字段存储第一个请求的结果,并在所有后续调用中重用它.@H_301_8@
@H_301_8@
private data: Data; getData() { if(this.data) { return Observable.of(this.data); } else { ... } }
可悲的是,可观察力的力量完全被忽略了 – 你手动完成所有的东西.事实上,如果我对将结果分配给局部变量/字段感到满意,我就不会寻找合适的解决方案.
我认为一个不好的做法的另一个重要的事情是服务不应该有一个状态 – 即应该没有包含从一个调用到另一个调用的数据的私有字段.清除缓存相当容易 – 只需将this.data设置为null,即可重新执行请求.@H_301_8@
2.这个答案https://stackoverflow.com/a/36413003/1063354建议使用ReplaySubject:@H_301_8@
@H_301_8@
private dataObs$= new ReplaySubject(1); constructor(private http: Http) { } getData(forceRefresh?: boolean) { // If the Subject was NOT subscribed before OR if forceRefresh is requested if (!this.dataObs$.observers.length || forceRefresh) { this.http.get('http://jsonplaceholder.typicode.com/posts/2').subscribe( data => this.dataObs$.next(data),error => { this.dataObs$.error(error); // Recreate the Observable as after Error we cannot emit data anymore this.dataObs$= new ReplaySubject(1); } ); } return this.dataObs$; }
看起来非常棒(再次 – 清除缓存没有问题)但我无法映射此调用的结果,即@H_301_8@
@H_301_8@
service.getData().map(data => anotherService.processData(data))
这是因为底层观察者没有调用其完整方法.我很确定很多反应方法也不适用于此.要实际获取数据,我必须订阅此observable,但我不想这样做:我想通过解析器获取我的一个组件的缓存数据,该解析器应该返回一个Observable(或Promise),而不是订阅:@H_301_8@
路线@H_301_8@
@H_301_8@
{ path: 'some-path',component: SomeComponent,resolve: { defaultData: DefaultDataResolver } }
解析器@H_301_8@
@H_301_8@
... resolve(route: ActivatedRouteSnapshot,state: RouterStateSnapshot): Observable<Data> { return this.service.getData(); }
永远不会激活组件,因为它的依赖性永远不会被解析.@H_301_8@
3.在这里https://stackoverflow.com/a/36296015/1063354我找到了一个使用publishLast().refCount()的提议.@H_301_8@
@H_301_8@
getCustomer() { return this.http.get('/someUrl') .map(res => res.json()).publishLast().refCount(); }
这满足了我对缓存和解析的要求但是我还没有找到一个干净整洁的解决方案来清除缓存.@H_301_8@
我错过了什么吗?任何人都可以想出一种更好的方法来缓存反应性可观察量能够映射其结果,以及一旦它不再相关就刷新缓存数据吗?@H_301_8@
@H_301_8@
您可以像以下一样使用它:@H_301_8@
@H_301_8@
let res = new RestResource(() => this.http.get('inline.bundleo.js')); res.status.subscribe((loading)=>{ console.log('STATUS=',loading); }); res.value.subscribe((value) => { console.log('VALUE=',value); });
和来源:@H_301_8@
@H_301_8@
export class RestResource { static readonly LOADING: string = 'RestResource_Loading'; static readonly ERROR: string = 'RestResource_Error'; static readonly IDLE: string = 'RestResource_Idle'; public value: Observable<any>; public status: Observable<string>; private loadStatus: Observer<any>; private reloader: Observable<any>; private reloadTrigger: Observer<any>; constructor(requestObservableFn: () => Observable<any>) { this.status = Observable.create((o) => { this.loadStatus = o; }); this.reloader = Observable.create((o: Observer<any>) => { this.reloadTrigger = o; }); this.value = this.reloader.startWith(null).switchMap(() => { if (this.loadStatus) { this.loadStatus.next(RestResource.LOADING); } return requestObservableFn() .map((res) => { if (this.loadStatus) { this.loadStatus.next(RestResource.IDLE); } return res; }).catch((err)=>{ if (this.loadStatus) { this.loadStatus.next(RestResource.ERROR); } return Observable.of(null); }); }).publishReplay(1).refCount(); } reload() { this.reloadTrigger.next(null); } }