我有一个服务,通过HTTP服务获取数据并返回一个可观察对象.
在第一次调用之后,我想在服务内部缓存结果,一旦新组件尝试获取数据,它将从缓存结果中获取它.
有一个简单的解决方案吗?
如果您将可观察对象作为共享数据的手段,则可以采用以下方法:
import { Injectable } from '@angular/core';
import { Http, Response } from '@angular/http';
import { Observable, ReplaySubject } from 'rxjs';
@Injectable()
export class CachedService {
data$: Observable = this.dataSubject.asObservable();
private dataSubject = new ReplaySubject(1);
constructor(private http: Http) { }
fetch() {
this.http.get(...).subscribe(res => this.dataSubject.next(res));
}
}
这将在调用fetch
方法时进行HTTP调用,并且任何订阅者都service.data$
将从中获取响应ReplaySubject
.当它重放之前的值时,在HTTP调用解析后加入的任何订阅者仍将获得先前的响应.
如果您想触发更新,您只需拨打电话service.fetch()
即可启动新的HTTP呼叫,一旦新响应到达,所有订户都将更新.
您的组件将看起来像:
@Component({ ... })
export class SomeComponent implements OnInit {
constructor(private service: CachedService) { }
ngOnInit() {
this.service.fetch();
this.service.data$.subscribe(...);
}
}
我最近为同事写了一篇关于这种方法的博客文章:http://blog.jonrshar.pe/2017/Apr/09/async-angular-data.html
我认为你不应该在构造函数中或在angular的生命周期中的任何时间执行fetch().正如你所说,ngOnInit
在角度服务中不起作用.
相反,我们希望利用rxjs通过流无缝传递缓存值 - 调用者不必知道有关缓存与非缓存值的任何信息.
如果组件需要数据,则无论是否为高速缓存,它都会对其进行预订.为什么要获取()您不确定它将被使用的数据?
缓存应该在更高级别实现.我认为这种实现是一个良好的开端:http: //www.syntaxsuccess.com/viewarticle/caching-with-rxjs-observables-in-angular-2.0
getFriends(){ if(!this._friends){ this._friends = this._http.get('./components/rxjs-caching/friends.json') .map((res:Response) => res.json().friends) .publishReplay(1) .refCount(); } return this._friends; }
我不确定这是最好的方法,但它更容易维护,因为它有一个单一的责任.只有当一个组件订阅它时,数据才会被缓存,无论什么/谁/哪个组件需要数据并且是第一个需要它的人.