RxJS Subjet
Subjectの発火箇所と、発火後のロジックは分ける。
const rx = require('rxjs'); const op = require('rxjs/operators'); let sbj = getSubject() sbj.next(1) sbj.next(2) sbj.complete() function getSubject() { let sbj = new rx.Subject sbj.subscribe(cl) return sbj } function cl(v) { console.log(v) }
RxJS if elseをどう表現するか
iif という関数がある。
iif自体は、Observableを返却する。
let arr = [1, 2, 3, 4, 5] rx.from(arr) .pipe( op.mergeMap(v => { return rx.iif( () => v % 2 === 0, rx.of(`偶数:${v}`), rx.of(`奇数:${v}`), ) }) ) .subscribe(cl) // 奇数:1 // 偶数:2 // 奇数:3 // 偶数:4 // 奇数:5
別にmapオペレータ内でif文を分岐させれば、十分な気がしてきた。
let arr = [1, 2, 3, 4, 5] rx.from(arr) .pipe( op.map(v => { if (v % 2 === 0) { return `偶数:${v}` } else { return `奇数:${v}` } }) ) .subscribe(cl) // 奇数:1 // 偶数:2 // 奇数:3 // 偶数:4 // 奇数:5
RxJS ループはfromで置き換える
ループはfromで置き換える。
ループはもう使わなくていいでしょ。
非同期通信じゃなくても、RxJS使っていく方向でいいんじゃないか。
と思ったりもする。
let arr = [1, 2, 3, 4, 5] rx.from(arr) .subscribe(cl)
RxJS if文はfilterオペレータに置き換える
if文はfilterオペレータに置き換えることが出来る。
rx.of(0, 1, 2, 3, 4)
.pipe(
op.filter(v => v % 2 === 0)
)
.subscribe(cl) // 0, 2, 4 と表示
RxJS 副作用のある処理はtap
ストリームと関係のない処理は、積極的にtapを使いたい。
パッと見で「副作用のある処理」が分かるようになる。見やすい。
let foo = rx.interval(1000).pipe(op.take(1)) foo.pipe( op.tap(cl) // 0と表示 ) .subscribe(cl) // 0と表示 function cl(v) { console.log(v) }
RxJS Promise.all()はforkJoinで書き換え
Promise.all()。
すべてのPromiseが発火されるのを待つ。
let foo1 = getPromise(123) let foo2 = getPromise('abc') Promise.all([foo1, foo2]) .then(cl) // [123, 'abc']
forkJoinで書き換えられる。
let bar1 = rx.interval(100).pipe(op.take(1)) let bar2 = rx.interval(1000).pipe(op.take(1)) rx.forkJoin(bar1, bar2) .subscribe(cl) // 1秒後に[0, 0]
pipeの中で使いたい場合は、mergeMapを使う。
rx.interval(1000).pipe(op.take(1)) .pipe( op.mergeMap(v => { let foo1 = rx.interval(100).pipe(op.take(1)) let foo2 = rx.interval(1000).pipe(op.take(1)) return rx.forkJoin(foo1, foo2) }) ) .subscribe(cl) // 2秒後に[0, 0]
共通メソッド。
function getPromise(v = 0) { return new Promise((resolve) => { setTimeout(() => resolve(v), 1000); }); } function cl(v) { console.log(v) }
RxJS 2度クリック防止
よくある「非同期通信が走るボタンクリックで、2度押し禁止」。
RxJSはexhaustMapで対応できる。
わざわざフラグ用の変数を作る必要がない。
const rx = require('rxjs'); const op = require('rxjs/operators'); rx.interval(100).pipe(op.take(5)) .pipe( op.exhaustMap(v => rx.of(v).pipe(op.delay(200))) // 0, 2, 4 と表示される // 1, 3 はキャンセルされる ) .subscribe(cl)