Angular HTTP Interceptor делает запросы один за другим - PullRequest
0 голосов
/ 09 апреля 2020


Задача : 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, и я смог получить доступ к каждому HTTP-событию или запросу из Observable, но с этого момента я не получил ни малейшего представления о том, как или возможно ли двигаться дальше с «задержкой» их. (Я все еще изучаю Rx Js и Angular связанные вещи)
Я также не уверен, что это решение le git или есть другая практика - возможно, лучшим решением будет создание более оптимизированного приложения , Также слышал о таком механизме, как кеширование HTTP-запросов. Если эти запросы не могут быть обработаны должным образом на «глобальном» уровне, мне придется погрузиться в приложение, чтобы восстановить его структуру, я думаю. Любые советы или советы, как бороться с такой вещью?

Заранее спасибо

Ответы [ 3 ]

1 голос
/ 09 апреля 2020

Я думаю, что один из способов решить эту проблему - использовать фасадный сервис.

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.

Вот разговор о Фасадах.

1 голос
/ 09 апреля 2020

Вы можете использовать операторы, такие как shareReplay , чтобы кешировать ваши HTTP-вызовы, чтобы возврат всегда оставался последним выданным значением и предоставлял опоздавшим абонентам доступ к нему без повторного выполнения вызова:

...
.pipe(
  shareReplay({ bufferSize: 1, refCount: true })
 )
0 голосов
/ 09 апреля 2020

Вы можете создать dataService, чтобы обернуть ваши http-вызовы и обработать кеширование там. С комбинацией BehaviorSubject и httpClient

_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);)
...