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


Похожие записи

Как добавить ng-bootstrap компоненты в проект Angular-CLI?

Покажу на примере нового проекта.

ng new project_name
cd project_name
npm install --save bootstrap@next
npm install --save @ng-bootstrap/ng-bootstrap

В angular-cli.json в секцию style надо добавить наш CSS, чтобы глобально подключить стили.

  "styles": [
    "styles.css",
    "../node_modules/bootstrap/dist/css/bootstrap.min.css"
  ],
17 августа 2017 г. в Angular

ngx translate attribute

Используется конструкция

<img src="image.jpg" [alt]="'KEY' | translate"> 
20 августа 2018 г. в Angular