Angular HTTP拦截器一个接一个地发出请求

时间:2020-04-09 10:04:35

标签: angular http rxjs interceptor angular-http-interceptors


问题:我正在使用的Angular应用在构造方面非常复杂。在某些情况下,同一组件的许多实例在同一位置(父组件)具有不同的数据输入,每个组件都会在应用程序中显示不同的图表,例如:
<sample-component [data]='data1> </sample-component> <sample-component [data]='data2> </sample-component> <sample-component [data]='data3> </sample-component> ... so on
,因此在每种情况下该数据的处理方式都不同,并且基于每个组件都对同一API端点进行相同的调用。因此,问题是,该调用在多个组件实例中突然执行了多次,这导致应用程序性能或服务器请求过多。

示例解决方案:我正在考虑Angular HTTP Interceptor,以及如何使用此工具捕获每个请求并在解决前一个请求时执行该请求,因此它们将一个接一个地触发。到目前为止,我已经实现了Interceptor,并且能够从Observable访问每个HTTP事件或请求,但是从这一点开始,我不知道如何或是否可以继续“延迟”它们。 (我仍在学习RxJ和Angular相关的东西)
我也不确定这是合法的解决方案还是其他实践-可能更好的解决方案是构建更优化的应用程序。还听说过诸如缓存HTTP请求之类的机制。如果不能在“全局”级别上正确处理这些请求,我想必须进入应用程序以重建其结构。有什么建议或提示如何处理这种事情?

预先感谢

3 个答案:

答案 0 :(得分:1)

您可以使用 shareReplay 之类的运算符来缓存您的http调用,以返回将始终是最后发出的值,并使迟到的订户可以访问它而无需再次执行该调用:

...
.pipe(
  shareReplay({ bufferSize: 1, refCount: true })
 )

答案 1 :(得分:1)

我认为解决此问题的一种方法是使用外观服务。

chart.facade.ts

chartData$: Observable<any>;

loadChartData () {
 this.chartData$ = this.http.get(...).pipe(shareReplay({ bufferSize: 1, refCount: true }));
}

parent.component.ts

ngOnInit () {
 this.charFacade.loadChartData();
}

现在我要说的是,这取决于您如何组织事物,但是据我了解,每个sample-component都会单独发出http调用。

sample.component.ts

// chartFacade.chartData$ - instantiated in `parent` component
this.chartData$ = this.chartFacade.chartData$;

constructor (private chartFacade: ChartFacade) { }

每次您在chartData$ | async组件模板中进行sample时, http调用只能进行一次,并且应该从ReplaySubject的缓存中检索结果。

refCount === true时,如果没有活动的订阅(例如,每个sample组件都被销毁),则ReplaySubject使用的shareReplay将被丢弃,这意味着再次加载这些组件时,将发生http调用,其结果将由新的ReplaySubject存储。

Here's关于立面的演讲。

答案 2 :(得分:0)

您可以创建一个dataService来包装您的http调用并在那里处理缓存。结合使用BehaviorSubjecthttpClient

_cache=new BehaviorSubject(null)
getData(){
   if(!this._cache.value){ 
       http.get(url).subscribe(this._cache)
   return this._cache.pipe(filter(data=>data),first())
}
invalidateCache(){ this._cache.next(null);)