サンプルコード書いたら大体理解できた。
利用シーンのイメージ:
- map: 値の変換操作
- concatMap: 同期処理など、キューイングして直列実行したい処理。
- mergeMap: TODOのDone操作など、並列実行したい処理。
- switchMap: リアルタイム検索のキーボード入力から検索する処理など、後続の処理のみ優先させたい場合。
- exhaustMap: フォームのサブミットなど、多重実行されたくない処理。
import { of } from 'rxjs';
import {
concatMap,
exhaustMap,
map,
mergeMap,
switchMap,
} from 'rxjs/operators';
const sleep = (ms: number) => {
return new Promise(resolve => {
console.log('sleep: start');
setTimeout(() => {
console.log('sleep: end');
resolve();
}, ms);
});
};
const array = [1, 2, 3];
/**
* map
* * Promiseは展開されない
* * 配列操作と同じ
*/
const mapExample = () => {
of(...array)
.pipe(
map(i => {
return sleep(1000).then(() => i * 2);
}),
)
.subscribe(i => console.log(i));
};
// 出力:
// Promise { <pending> }
// Promise { <pending> }
// Promise { <pending> }
/**
* concatMap
* * Promiseが展開される
* * 連続で値が流れてきた場合は直列で実行される。
*/
const concatMapExample = () => {
of(...array)
.pipe(
concatMap(i => {
return sleep(1000).then(() => i * 2);
}),
)
.subscribe(i => console.log(i));
};
// 出力:
// sleep: start
// sleep: end
// 2
// sleep: start
// sleep: end
// 4
// sleep: start
// sleep: end
// 6
/**
* mergeMap
* * Promiseが展開される
* * 連続で値が流れてきた場合は並列で実行される。
*/
const mergeMapExample = () => {
of(...array)
.pipe(
mergeMap(i => {
return sleep(1000).then(() => i * 2);
}),
)
.subscribe(i => console.log(i));
};
// 出力:
// sleep: start
// sleep: start
// sleep: start
// sleep: end
// 2
// sleep: end
// sleep: end
// 4
// 6
/**
* switchMap
* * Promiseが展開される
* * 連続で値が流れてきた場合は並列で実行され、ストリームには最後の結果しか流れない。
*/
const switchMapExample = () => {
of(...array)
.pipe(
switchMap(i => {
return sleep(1000).then(() => i * 2);
}),
)
.subscribe(i => console.log(i));
};
// 出力:
// sleep: start
// sleep: start
// sleep: start
// sleep: end
// sleep: end
// sleep: end
// 6
/**
* exhaustMap
* * Promiseが展開される
* * 連続で値が流れてきた場合は最初のPromiseのみ実行され、実行中は後続の値を切り捨てる。
*/
const exhaustMapExample = () => {
of(...array)
.pipe(
exhaustMap(i => {
return sleep(1000).then(() => i * 2);
}),
)
.subscribe(i => console.log(i));
};
// 出力:
// sleep: start
// sleep: end
// 2
(async () => {
// 動作確認はコメントを切り替える
mapExample();
// switchMapExample();
// mergeMapExample();
// concatMapExample();
// exhaustMapExample();
})();