カテゴリー
【Rxjs基礎講座】deferとfromでPromiseをObservableへ変換するときの注意点
※ 当ページには【広告/PR】を含む場合があります。
2020/03/13
2022/10/05
今回もrxjsのお勉強したい方のためのテクニカルメモです。
javascriptのライブラリーには
Promise
rxjs
Promise
Observable
そこで大活躍するのが、
defer
from
これらの標準メソッドはどちらも
Promise
Observable
公式では
なお関連記事でasync/awaitをdeferへ変換する方法を解説した内容もよろしけばご参照ください。
deferとfromでコールバック関数の応答が違う
Rxjsで同期処理を行う際に、Javascriptネイティブの関数である
Promise
Observable
defer
from
でもこの2つのオペレーターの挙動の違いを理解せず混同して利用していると、意図としないタイミングで同期処理されて、期待した結果がコールバックのレスポンスから返って来ない可能性もあります。
今回の内容のキモとしては以下の点を予め考慮しておくことです。
+ fromオペレーター:
コールバックで返される値のタイミングの調整が不要な場合に利用
+ deferオペレーター:
コールバックで返される値がタイミング・クリティカルな場合に利用
このような違いがあるので、同期的な処理を設計する場合には、まず
defer
簡単な同期を与えるサンプルプログラム
deferとfromの作用の違いを比較する前に、簡単な同期処理を与えるストリームを作成します。
以下のコードで実行された時間を出力します。
import { EMPTY, tap, defaultIfEmpty } from 'rxjs';
const empty$ = EMPTY.pipe(
defaultIfEmpty(null),
tap(_ => console.log(new Date())) // 👈ここに到達した時の時間を出力
);
empty$.subscribe();
これは
EMPTY
defaultIfEmpty
tap
このコードを実行すると、ストリームがアタッチされたときの時間が得られます。
2020-03-13T03:47:07.948Z
fromとdeferの比較実験
では先程のプログラムを修正しながらfromとdeferの作用のObservable変換後の作用の違いを具体例をあげて見ていきましょう。
実験① ~ fromの場合
挙動がもっとも単純な
from
import { EMPTY, from, tap, delay, defaultIfEmpty, switchMap } from 'rxjs';
const empty$ = EMPTY.pipe(
defaultIfEmpty(null),
tap(_ => console.log(new Date())) // 👈ここに到達した時の時間を出力①
);
const from$ = from(new Promise(resolve => {
resolve(new Date()); // 👈ここに到達した時の時間を出力②
})).pipe(
tap(time => console.log(time))
);
empty$.pipe(
delay(2000), // 👈2秒遅らせてfrom$に遷移
switchMap(_ => from$) // 👈from$の内部のPromiseのコールバックは2秒遅れる?遅れない?
).subscribe();
実行すると、
2020-03-13T04:04:11.330Z #①の時間
2020-03-13T04:04:11.329Z #②の時間
というように、マークされた時間はほぼ同着です。
つまりは、
empty$
from$
from
実験② ~ deferの場合
これを
defer
import { EMPTY, defer, tap, delay, defaultIfEmpty, switchMap } from 'rxjs';
const empty$ = EMPTY.pipe(
defaultIfEmpty(null),
tap(_ => console.log(new Date())) // 👈ここに到達した時の時間を出力①
);
const defer$ = defer(() => new Promise(resolve => {
resolve(new Date()); // 👈ここに到達した時の時間を出力②
})).pipe(
tap(time => console.log(time))
);
empty$.pipe(
delay(2000), // 👈2秒遅らせてdefer$に遷移
switchMap(_ => defer$) // 👈defer$の内部のPromiseのコールバックは2秒遅れる?遅れない?
).subscribe();
ほとんどコード自体は先程の
from
from
defer
出力のほうが、
2020-03-13T04:17:36.233Z #①の時間
2020-03-13T04:17:38.238Z #②の時間
どうでしょうか、今回は2秒ほど遅延して実行されているのが分かります。
よって
from
subscribe
defer
まとめ
では再度今回のおさらいをしておきます。
今回のことをざっくりとまとめると、
+ fromオペレーター:
コールバックで返される値のタイミングが不要な場合に利用する
+ deferオペレーター:
コールバックで返される値のタイミングが重要な場合に利用する
Promise
Observable
defer
from
特に
defer
記事を書いた人
ナンデモ系エンジニア
主にAngularでフロントエンド開発することが多いです。 開発環境はLinuxメインで進めているので、シェルコマンドも多用しております。 コツコツとプログラミングするのが好きな人間です。
カテゴリー