【问题标题】:Angular HTTP Interceptor make requests one after anotherAngular HTTP 拦截器一个接一个地发出请求
【发布时间】:2020-07-21 22:13:04
【问题描述】:


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

示例解决方案: 我在考虑 Angular HTTP 拦截器,以及如何使用此工具捕获每个请求并在前一个请求解决时使其执行,这样它们就会一一触发.到目前为止,我实现了拦截器,并且能够访问来自 Observable 的每个 HTTP 事件或请求,但是从这一点开始,我不知道如何或是否可以继续“延迟”它们。 (我还在学习 RxJs 和 Angular 相关的东西)
我也不确定这是否是合法的解决方案或有其他做法 - 可能更好的解决方案是构建更优化的应用程序。还听说过缓存 HTTP 请求等机制。如果无法在“全局”级别正确处理这些请求,我猜我将不得不深入应用程序以重建其结构。任何建议或提示如何处理此类事情?

提前致谢

【问题讨论】:

  • 您是否考虑过在智能组件中发出请求一次,然后将数据传递给多个sample-componentinstances(哑组件) ?
  • 是的,这是另一种解决方案,但在触及组件和服务的逻辑并重建它之前,我想尝试在更高级别处理它,以便负责请求的组件和服务保持不变。

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


【解决方案1】:

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

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

【讨论】:

  • 你会把它放在哪里更精确?
【解决方案2】:

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

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) { }

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

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

Here's 一场关于 Facades 的演讲。

【讨论】:

    【解决方案3】:

    您可以创建一个 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);)
    

    【讨论】:

      猜你喜欢
      • 2016-09-19
      • 1970-01-01
      • 2023-03-18
      • 1970-01-01
      • 1970-01-01
      • 2022-11-02
      • 1970-01-01
      • 2018-03-30
      • 2019-02-23
      相关资源
      最近更新 更多