Подождите, пока все наблюдаемые в mergeMap завершатся, прежде чем испускать настраиваемое значение
Я хочу обрабатывать список наблюдаемых одновременно, используя flatMap
а затем выдать одно пустое значение при обработке всех внутренних наблюдаемых. Есть ли элегантный способ добиться этого, то есть с помощью одного оператора?
Вот пример:
const { of, from } = Rx.Observable;
from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
.mergeMap(number => multiply(number), 2) // processing two numbers at a time
.last() // waiting for all inner observables to complete
.map(_ => undefined) // casting a value returned by last() to an empty value
.subscribe()
;
function multiply(number) {
return of(number * 2) // multiplying the number
.delay(200) // adding a slight delay
;
}
Я знаю, что могу использовать toArray()
или last()
чтобы дождаться завершения всех внутренних наблюдаемых, но тогда мне нужно будет привести его к пустому значению, используя map()
оператор (как в моем примере выше).
Думаю, я ищу оператор со следующей семантикой: emit X when source observable completes
, например:
from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
.mergeMap(number => multiply(number), 2)
.emitOnComplete(undefined)
.subscribe(console.log) // we should get undefined here
;
2 ответа
На самом деле есть одно хитрое решение, использующее reduce()
который излучается только один раз, когда его наблюдаемый источник завершается. Вы можете использовать его, чтобы игнорировать все значения и просто вернуть начальное значение:
from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
.pipe(
mergeMap(number => multiply(number), 2),
reduce((acc, value) => acc, undefined),
)
.subscribe(console.log);
Живая демонстрация: https://stackblitz.com/edit/rxjs-tx6bbe
Кстати, забавный факт: тот же трюк с reduce()
используется внутри пакета Angular Router (только без начального значения).
Самый удобный способ, которым мне удалось найти до сих пор является объединение ignoreElements оператора с ENDWITH:
from([1, 2, 3, 4, 5])
.mergeMap(number => multiply(number), 2)
.ignoreElements()
.endWith(undefined)
.subscribe(console.log) // getting undefined here
;
Однако было бы неплохо иметь для этого одного оператора.