RxJS-массив наблюдаемых HTTP-объектов: запускать следующий только после завершения предыдущего

У меня есть массив наблюдаемых (запросы HTTP POST), которые мне нужно отправить в API после определенного события. Ниже приведен упрощенный пример подхода, в котором я использую concat, чтобы использовать успешные, ошибочные и полные обратные вызовы.

// build up an array of stored POST requests to fire off later
// array is indeterminate length, could be 1 request could be 1,000
let requests = [ req1, req2, req3, req4 ];

concat(...requests).subscribe(
  success => ... handle success ...
  error => ... handle error ...
  () => ... handle completion ...
);

Проблема в том, что concat в основном отправляет все запросы одновременно, что повышает вероятность проблем параллелизма в API, потребляющем запросы. Эта проблема должна быть решена, если я смогу запускать запросы один за другим, а не все сразу. Я определил, что цикл forEach не подходит.

Существует ли подход RxJS, при котором req2 генерируется только после завершения req1, а req3 — только после завершения req2 и так далее? Я просматривал документы RxJS, но пока не нашел ничего, что соответствовало бы этому сценарию.


person Nathan Beck    schedule 09.10.2020    source источник
comment
Используйте асинхронное ожидание для зависимостей, использующих замыкания. Преобразуйте наблюдаемые в обещания, чтобы это было сделано.   -  person JWP    schedule 10.10.2020
comment
Проблема в том, что concat в основном отправляет все запросы сразу -> concat должен запускать наблюдаемые последовательно, переходя к последующим запросам только после завершения первого. Пример   -  person BizzyBob    schedule 10.10.2020
comment
Ваш код с concat должен работать по назначению. Если это не так, предоставьте stackblitz, который воспроизводит проблему.   -  person frido    schedule 12.10.2020


Ответы (1)


Вы можете использовать функцию RxJS from и оператор сопоставления более высокого порядка concatMap.

Попробуйте следующее

from(requests).pipe(
  concatMap(req => req)
).subscribe(
  success => ... handle success ...
  error => ... handle error ...
  () => ... handle completion ...
);

Без оператора concatMap элементы запроса массива будут дословно выдаваться как наблюдаемые, а не запускаться. Вы можете найти различия между операторами отображения более высокого порядка в моем другом ответе здесь.

person Michael D    schedule 09.10.2020
comment
@RafiHenig: concat должен отправлять запросы последовательно. Но вы говорите, что (он) в основном отправляет все запросы сразу. И, не видя характера запросов, мой ответ — это следующая альтернатива, которую я мог придумать. Это обеспечивает последовательность выбросов. Вы можете увидеть различия в этом Stackblitz. - person Michael D; 11.10.2020