我需要防止对某些路由进行多次 api 调用。 我一直听说我应该使用
shareReplay()
来防止多次 api 调用,尤其是当您在页面之间切换并返回同一页面时。我已经使用了 shareReplay()
,但是当我查看网络选项卡时,它继续发出网络请求。有任何想法吗?我在这里创建了一个 stackblitz 链接 = https://stackblitz.com/edit/angular-ivy-jadosn
这是我的
http.services
代码:
getWaterPokemon(): Observable<Filter[]> {
return this.http.get<Filter[]>(`${this.getApi()}/type/5`, { responseType: 'json' }).pipe(
map((clients: any) => clients.pokemon.map((client: any) => client.pokemon)),
shareReplay()
);
}
这是我的
water.component
代码:
ngOnInit(): void {
this.waterPokemon$ = this.httpService.getWaterPokemon().pipe(
shareReplay()
);
}
每次进入水精灵页面时,您都会看到网络请求发生。
这不是可观察量的工作方式。
让我解释一下(虽然很长但很有用)。
可观察量有两种类型:热或冷。
HOT observable 是一个连续发出值而不被关闭的 observable。将其视为 HTML 元素上的事件侦听器。
COLD observable 是在第一次调用后完成的 observable。把它想象成一个承诺。
因此,使用
http.get
很冷,而在可观察量上使用 shareReplay
则很热
您在这里所做的事情如下:
使用您当前的代码,所有服务所做的就是每次调用获取函数时返回一个 HOT observable(在本例中这是无用的)。
您想要做的是存储获取的结果,这样您就不必每次都调用该服务。
这个想法是
// Service
class FetchService() {
data = new BehaviorSubject<any[]>([]);
data$ = this.data.asObservable();
constructor(private http: HttpClient) {
http.get('url').subscribe(res => this.data.next(res));
}
}
// Component
class MyComponent {
data$ = this.service.data$;
constructor(private service: FetchService) {}
}
这样,服务在实例化时仅刷新数据一次。但是,由于该服务是单例(除非以其他方式制作),因此即使您更改页面,它的实例也会存在(组件的情况并非如此,每当您路由进/出它时,组件就会被销毁并重新创建)。
然后,该组件只需获取您服务中的记忆数据,从而防止您的应用进一步调用 API。