我有一个共享服务(从this建议开始)缓存并在第一次http请求后返回一些数据:
export class SharedService {
constructor(private http:Http) {
}
getData() {
if (this.cachedData) {
return Observable.of(this.cachedData);
} else {
return this.http.get(...)
.map(res => res.json())
.do((data) => {
this.cachedData = data;
});
}
}
}
我的问题是我在同一模板中有一些指令和组件,它们都是同时初始化的,每一个都同时调用(在ngInit函数内)getData方法(所有这些都在第一个成功之前)所以该服务启动许多http请求而不是返回缓存数据。 有人可以建议我如何避免这种副作用吗?
答案 0 :(得分:3)
您的解决方案并未涵盖所有案例。
将其与https://stackoverflow.com/a/36291681/217408
中的方法进行比较getData() {
if(this.data) {
// if `data` is available just return it as `Observable`
return Observable.of(this.data);
else if(this.observable) {
// if `this.observable` is set then the request is in progress
// return the `Observable` for the ongoing request
return this.observable;
} else {
// create the request, store the `Observable` for subsequent subscribers
this.observable = this.http.get('/someUrl')
.map(res => res.json())
.do(val => {
this.data = val;
// when the cached data is available we don't need the `Observable` reference anymore
this.observable = null;
})
// make it shared so more than one subscriber can get the result
.share();
return this.observable;
}
}
在请求未返回之前,您需要将从第一个请求创建的Observable
返回到后续请求,直到第一个请求完成。
https://stackoverflow.com/a/36296015/217408也显示了有趣的方法,但由于缺点(取决于您的要求),请求无法取消。
另外,请确保您已将您的共享服务仅作为提供商注册一次,如@MichaelD所述。
Angular团队建议使用根组件的providers: [...]
列表而不是bootstrap(...)
,但没有技术原因。他们认为它更易于维护。
答案 1 :(得分:1)
您必须在bootstrap方法中声明您的服务:
bootstrap(AppComponent, [SharedService]);
该服务只会实例化一次(单身),因此它可以解决您的问题。