RXJS mergeMap/flatMap
mergeMap(
project: function: Observable,
resultSelector: function: any,
concurrent: number
): Observable
Преобразовать каждое испускаемое значение в наблюдаемый объект.
flatMap
- это псевдоним дляmergeMap
Если будет активна только одна внутренняя подписка в конкретный промежуток времени, попробуйте использовать switchMap
Если порядок испускания элементов, подписки для внутренних наблюдаемых являются важными, попробуйте concatMap
Зачем использовать mergeMap?
Этот оператор лучше всего подходит, если нужно наложить каждый элемент потока на внутренний наблюдаемый объект, но необходимо вручную контролировать количество внутренних подписок.
Для экземпляров использующих switchMap
каждая внутренняя подписка завершается, когда источник испускает значение, то есть всегда существует только одна активная внутренняя/локальная подписка. Напротив, mergeMap
позволяет быть активными нескольким активным локальным подпискам. И поэтому, один из распространенных вариантов использования mergeMap
это запросы, которые не должны быть отменены или прерваны. Если нужно управлять порядком выполнения запросов, то concatMap
будет лучшим вариантом.
Следует помнить, так как mergeMap
поддерживает сразу несколько активных локальных подписок, очень легко создать "утечки памяти", создавая долговременные подписки. Примером может служить использование таймеров или событий DOM. В подобных случаях, если вы все же решили использовать mergeMap
, нужно подумать об использовании операторов take
и takeUntil
для управления завершением подписки.
Ограничить общее количество внутренних/локальных подписок можно параметром concurrent
.
Пример с наблюдаемым
import {of} from 'rxjs'
import {mergeMap} from 'rxjs/operators'
// отправляем 'hello'
const source = of('hello')
//
const example = source.pipe(mergeMap(_ => of(`${_} World!`)))
// подписка
const sub = example.subscribe(console.log)
Пример с Promise
import {of} from 'rxjs'
import {mergeMap} from 'rxjs/operators'
// испускаем 'hello'
const source = of('Hello')
// mergeMap также может испускать результат от Promise
const myPromise = _ => new Promise(resolve => resolve(`${_} World from Promise!`))
// наложить на Promise
const example = source.pipe(mergeMap(_ => myPromise(_)))
Пример использования resultSelector
import {of} from 'rxjs'
import {mergeMap} from 'rxjs/operators'
/*
вторым аргументом можно указать функцию (resultSelector), в которую будут переданы: исходное значение и испускаемое значение от локального наблюдаемого объекта или "промиса"
*/
// испускаем 'hello'
const source = of('hello')
// mergeMap может принимать Promise и испускать его значение (resolve)
const myPromise = _ => new Promise(resolve => resolve(`${_} from Promise!`))
// обработка потока
const example = source.pipe(
mergeMap(
_ => myPromise(_),
(valueFromSource, valueFromPromise) => {
return `source: ${valueFromSource}, promise: ${valueFromPromise}`
}
)
)
//
const sub = example.subscribe(console.log)