RxJS Subject
Subjectは、Observable + Observer である。
Subjectはユニキャストできる。
Subjectは、Subjectオブジェクト作成後、後々ストリームを流せる。
Observableオブジェクトより、使い勝手が良さそう?
let sbj = new Subject sbj.subscribe((val) => console.log(val)) sbj.subscribe((val) => console.log(val * 10)) sbj.next(1) // 1, 10 sbj.next(2) // 2, 20 sbj.next(3) // 3, 30
RxJS tap
前回と同じ、こちら共通関数。
function sto(x, time = 1000) { const observable = new Observable(subscriber => { setTimeout(() => { subscriber.next(x) subscriber.complete() }, time); }); return observable } function cl(x) { console.log(x) }
副作用のある処理は、tapに書く。
パッと見で、とても分かりやすい。
let obs = sto(1) let meta = 'foo' obs.pipe( tap(() => { cl(meta) // 'foo' meta = 'bar' }) ) .subscribe(() => { cl(meta) // 'bar' })
RxJS mergeMap, concatMap, switchMapの違い
以下、共通関数。
function sto(x, time = 1000) { const observable = new Observable(subscriber => { setTimeout(() => { subscriber.next(x) subscriber.complete() }, time); }); return observable } function cl(x) { console.log(x) }
- mergeMap
of(0, 1, 2).pipe( mergeMap(x => sto(x + 1, 1000)) ) .subscribe(cl)
1,2,3 と同時に表示される。
- concatMap
of(0, 1, 2).pipe( concatMap(x => sto(x + 1, 1000)) ) .subscribe(cl)
1,2,3 と1秒間隔で表示される。
- switchMap
of(0, 1, 2).pipe( switchMap(x => sto(x + 1, 1000)) ) .subscribe(cl)
3 と表示される。
1,2 はキャンセルされる。
Observable resolveする方法
Promiseのresolve( )に該当するのが、Observableのnext( )になる。
Observable.create((observer) => { setTimeout(() => { observer.next(1) }, 1000) }) .pipe( map(val => Number(val) + 2), map(val => Number(val) * 3), ) .subscribe(val => { console.log(val) // 1秒後に"9" })
Angular Observable, Promiseの相互変換
ObservableもPromiseも、似たようなもんだと思ってます。
import { from as fromPromise } from 'rxjs'; const foo = this.http.get('http://localhost:3000/') console.log(foo) // Observable foo.subscribe(res => console.log(1, res)) const bar = foo.toPromise() console.log(bar) // Promise bar.then(res => console.log(2, res)) const baz = fromPromise(bar) console.log(baz) // Observable baz.subscribe(res => console.log(3, res))
test
" copy file path command! -nargs=0 CopyFilePath call s:Clip(expand('%:p')) nnoremap <space>f :CopyFilePath<CR> command! -nargs=0 CopyDirPath call s:Clip(expand('%:p:h')) nnoremap <space>d :CopyDirPath<CR> command! -nargs=0 CopyCwd call s:Clip(getcwd()) nnoremap <space>c :CopyCwd<CR> nnoremap <space>m :cd %:h<CR>:echo "CWD => " . getcwd()<CR> function! s:Clip(data) let @*=a:data echo "clipped: " . a:data endfunction
Promise then, catchの連結
以下のコードは、どのような出力になるか?
const promise = Promise.reject() promise .then(() => console.log(1)) .catch(() => console.log(2)) .then(() => console.log(3)) .catch(() => console.log(4)) .then(() => console.log(5)) .catch(() => console.log(6))
答えは「2, 3, 5」
初めの変数promiseは、rejectされたPromiseオブジェクト。
1のthenは、rejectされたPromiseオブジェクトだから通らない。
2のcatchは、rejectされたPromiseオブジェクトだから通る。
同時にreturnされたと見なされ、resolveされたPromiseオブジェクトが返却される。
3のthenは、resolveされたPromiseオブジェクトだから通る。
同時にreturnされたと見なされ、resolveされたPromiseオブジェクトが返却される。
4のcatchは、resolveされたPromiseオブジェクトだから通らない。
5のthenは、resolveされたPromiseオブジェクトだから通る。
同時にreturnされたと見なされ、resolveされたPromiseオブジェクトが返却される。
6のcatchは、resolveされたPromiseオブジェクトだから通らない。