【发布时间】:2017-09-09 07:17:28
【问题描述】:
我发现了许多缓存响应式可观察对象的方法,更具体地说,缓存 http 请求的结果。但是,由于以下原因,我对建议的解决方案并不完全满意:
1. 这个答案https://stackoverflow.com/a/36417240/1063354 使用一个私有字段来存储第一个请求的结果,并在所有后续调用中重复使用它。
代码:
private data: Data;
getData() {
if(this.data) {
return Observable.of(this.data);
} else {
...
}
}
可悲的是,observables 的力量被完全忽略了——你手动完成所有的事情。事实上,如果我对将结果分配给局部变量/字段感到满意,我不会寻找合适的解决方案。 我认为一个不好的做法的另一件重要的事情是服务不应该有状态 - 即不应该有包含数据的私有字段,这些数据会随着调用而改变。 清除缓存相当容易 - 只需将 this.data 设置为 null 即可重新执行请求。
2.这个答案https://stackoverflow.com/a/36413003/1063354建议使用ReplaySubject:
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$;
}
看起来非常棒(同样 - 清除缓存没问题)但我无法映射此调用的结果,即
service.getData().map(data => anotherService.processData(data))
这是因为底层观察者没有调用它的 complete 方法。我很确定很多反应式方法在这里也不起作用。要真正获取数据,我必须 订阅 这个 observable 但我不想这样做:我想通过 解析器获取我的一个组件的缓存数据> 应该返回一个Observable(或Promise),而不是一个Subscription:
路线
{
path: 'some-path',
component: SomeComponent,
resolve: {
defaultData: DefaultDataResolver
}
}
解析器
...
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Data> {
return this.service.getData();
}
组件从不激活,因为它的依赖关系从不解决。
3.在这里https://stackoverflow.com/a/36296015/1063354我找到了一个使用publishLast().refCount()的建议。
代码:
getCustomer() {
return this.http.get('/someUrl')
.map(res => res.json()).publishLast().refCount();
}
这满足了我对缓存和解析的要求但是我还没有找到一个干净整洁的解决方案来清除缓存。
我错过了什么吗?谁能想出一种更好的方法来缓存反应性可观察对象,以便能够映射其结果并在缓存数据不再相关时刷新缓存数据?
【问题讨论】:
标签: angular rxjs angular2-services