Объединение нескольких HTTP-запросов в Angular
В статье мы рассмотрим метод отправки нескольких параллельных HTTP запросов в Angular, используя Observable.forkJoin.
Допустим, у нас есть 2 конечных точки API, которые предоставляют 2 разных набора данных. Мы хотим создать список в нашем приложении, используя оба набора данных.
getVehicles(): Observable< any > { const cars = this.http.get(CARS_ENDPOINT).map(res => res.json()); const bikes = this.http.get(BIKES_ENDPOINT).map(res => res.json()); }
Мы можем использовать RxJS forkJoin, чтобы объединить ответы от двух запросов:
import { forkJoin, Observable } from 'rxjs'; import { tap } from 'rxjs/operators'; @Injectable({ providedIn: 'root' }) export class DataService { constructor( private httpClient: httpClient, ) { } getVehicles(): Observable< any > { return forkJoin( this.httpClient.get(CARS_ENDPOINT), this.httpClient.get(BIKES_ENDPOINT) ).pipe( tap(response => { // responses[0] => cars // responses[1] => bikes }) ); } }
Заметить, что:
- Переменная response, которую мы получаем из Observable.forkJoin, представляет собой массив из 2 элементов - столько же, сколько элементов в массиве, который мы передаем forkJoin.
- Порядок значений в ответах также совпадает с порядком параметров.
- Оба запроса выполняются параллельно, но массив ответов отправляется, когда все запросы получают данные от своих конечных точек, то есть он должен ждать завершения всех запросов, а затем мы получаем значение массива ответов.
Разбирать массив не очень удобно, очередность может изменится и под индексом 0 могут оказаться другие данные, для того чтобы быть уверенными в том что вы используете нужные данные можно воспользоваться оператором tap и подписаться на изменения в самом запросе а не в forkJoin, как в примере ниже:
import { forkJoin, Observable } from 'rxjs'; import { tap } from 'rxjs/operators'; @Injectable({ providedIn: 'root' }) export class DataService { constructor( private httpClient: httpClient, ) { } getVehicles(): Observable< any > { return forkJoin( this.httpClient.get(CARS_ENDPOINT).pipe( tap(response => this.cars = response) ), this.httpClient.get(BIKES_ENDPOINT).pipe( tap(response => this.bikes = response) ) ); } }
Обратите внимание, чтобы отправить запросы у forkJoin необходимо вызвать метод subscribe