Angular параллельные и последовательные запросы на RxJS
Допустим имеется задача выполнить 3 параллельных запроса, и на основе их результата выполнить четвёртый запрос.
forkJoin - параллельные запросы
forkJoin
- это аналог поведения Promise.all
на RxJS Observables.
Ожидает пока все переданные Observables завершатся, а затем объединяет в массив последние значения, которые они выкидывают.
forkJoin
принимает любое число Observables
, которые могут передаваться как массив либо как аргументы. Если никаких входных Observables
не будет предоставлено, итоговый поток будет завершен немедленно. Если хотя бы один из переданных Observable
не выкинет значение и завершится, то forkJoin
тоже не выкинет значение.
// параллельно
forkJoin(
this._requestService.makeRequest1(),
this._requestService.makeRequest2(),
)
.subscribe(([res1, res2]) => {
this.propOne = res1;
this.propTwo = res2;
});
mergeMap - последовательные запросы
mergeMap
совмещает пришедший поток и запускаемый поток. Элементы пришедшего потока порождают новый поток. Этот оператор избавляет от подписки в подписке.
import { of } from 'rxjs';
import { mergeMap } from 'rxjs/operators';
const source = of('Hello');
const example = source.pipe(mergeMap(val => of(`${val} World!`)));
example.subscribe(console.log); // выведет: 'Hello World!'
Применительно к запросом
// последовательно
this._requestService.makeRequest1().pipe(
mergeMap((res1) => this._requestService.makeRequest2(res1)),
),
.subscribe(res2 => {
this.propTwo = res2;
});
Пример
Возвращаясь к задаче.
import { Component, Injectable, OnInit } from '@angular/core';
import { forkJoin, of } from 'rxjs';
import { delay, mergeMap, tap } from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class RequestService {
makeRequest(value: string, delayDuration: number) {
// симуляция http запроса
return of(`${value} завершён`).pipe(
delay(delayDuration)
);
}
makeAnotherRequest(...args) {
// симуляция http запроса
return of(args.join()).pipe(
delay(1000)
);
}
}
@Component({
selector: 'my-app',
template: `
<div>
<h1>forkJoin + mergeMap</h1>
<ul>
<li>{{ propOne }}</li>
<li>{{ propTwo }}</li>
<li>{{ propThree }}</li>
<li>{{ propFour }}</li>
</ul>
</div>
`,
})
export class AppComponent implements OnInit {
public propOne: string;
public propTwo: string;
public propThree: string;
public propFour: string;
constructor(private _requestService: RequestService) {}
ngOnInit() {
// симуляция 3 запросов с разным временем ответа
forkJoin(
this._requestService.makeRequest('Запрос 1', 1500),
this._requestService.makeRequest('Запрос 2', 500),
this._requestService.makeRequest('Запрос 3', 2500)
)
.pipe(
tap(([res1, res2, res3]) => {
this.propOne = res1;
this.propTwo = res2;
this.propThree = res3;
}),
mergeMap(result => this._requestService.makeAnotherRequest(result))
)
.subscribe(res4 => {
this.propFour = res4;
});
}
}
Посмотреть пример на Stackblitz