Rxjs:Observable.combineLatestとObservable.forkJoin


86

ちょうど間の違いであるのだろうかObservable.combineLatestObservable.forkJoin?私が見る限り、唯一の違いは、最新の値forkJoincombineLatest返しながら、Observablesが完了することを期待していることです。


4
注:ではrxjs6 +これらは今だけですcombineLatest()forkJoin()、観察を作成する機能。それらは同じことをしますが、構文は異なります。混同しないでくださいcombineLatestからrxjs/operators「pipeable」演算子あります。間違ったものをインポートすると、エラーが発生します。
Simon_Weaver

回答:


129

forkJoinすべての入力オブザーバブルを完了する必要があるだけでなく、入力オブザーバブルによって生成された最後の値の配列である単一の値を生成するオブザーバブルも返します。つまり、最後の入力オブザーバブルが完了するまで待機してから、単一の値を生成して完了します。

対照的に、combineLatestすべての入力オブザーバブルが少なくとも1つの値を生成すると、入力オブザーバブルが実行するたびに新しい値を生成するオブザーバブルを返します。これは、無限の値を持つ可能性があり、完了しない可能性があることを意味します。また、値を生成する前に入力オブザーバブルを完了する必要がないことも意味します。


@GregL forkJoinのように機能するが、失敗したhttp呼び出しでも機能する関数はありますか?
Tukkan 2017

2
@Tukkan、エラーから回復する演算子を各httpオブザーバブルにチェーンするので、エラーが発生する可能性のある複数のオブザーバブルを組み合わせる演算子を探すのではなく、エラー時に各リクエストに使用する値を定義します(Iそのような演算子が存在するかどうかはわかりません)。エラーから回復演算子は含ま.catch().onErrorResumeNext()おそらく、および.retry()(HTTP呼び出しが断続的に失敗する可能性がある場合)。
gregL 2017

1
明確にするために、どちらも配列を生成します。
Simon_Weaver

@Simon_Weaver必ずしもそうとは限りません。の場合combineLatest()、入力オブザーバブルの最新の値から出力値を生成する方法を指定する射影関数を指定できます。デフォルトでは、指定しない場合、発行された最新の値の配列を取得します。
GregL

CombineLatestからの各放出は、収集された値の配列です。forkjoinの配列についてのみ言及したので、それを追加したかっただけです。そのように、それらは同じです。そして、はい、RxJSには常に微妙な点があるので、何かを見逃した場合は、あなたが何を意味していたかを明確にできますか。
Simon_Weaver

14

また:

CombineLatest(...)は、オブザーバブルを1つずつ順番に実行します

combineLatest内部的にはを使用しますconcat。これは、次の配列に移動する前に、配列内のオブザーバブルごとに値を取得する必要があることを意味します。

// partial source of static combineLatest (uses the rxjs/operators combineLatest internally):
// If you're using typescript then the output array will be strongly typed based on type inference
return function (source) { return source.lift.call(from_1.from([source].concat(observables)), 
                           new combineLatest_1.CombineLatestOperator(project)); };

forkJoin(...)は、オブザーバブルを並行して実行します。

3つのソースオブザーバブルがあり、それぞれの実行に5秒かかる場合、実行には15秒かかりcombineLatestます。一方forkJoin、それは5秒かかりますので、それらを並列に実行します。

したがって、順序が強制されていない場合のforkJoinようPromise.all(...)に機能します。

エラー処理に関する考慮事項:

オブザーバブルのいずれかがエラーになった場合combineLatest、後続のオブザーバブルは実行されませんが、forkJoinすべて実行されています。したがってcombineLatest、オブザーバブルの「シーケンス」を実行し、結果をすべてまとめて収集すると便利です。


高度な注意:ソースオブザーバブルがすでに「実行中」(他の何かによってサブスクライブされている)でありshare、それらで使用している場合、この動作は表示されません。

さらに高度な注意:CombineLatestは常に各ソースから最新のものを提供するため、ソースオブザーバブルの1つが複数の値を出力する場合は、最新のものを取得します。ソースごとに1つの値を取得して、次の値に移動するだけではありません。各ソースオブザーバブルの「次の利用可能なアイテム」のみを取得する必要がある場合は.pipe(take(1))、入力配列に追加するときにソースオブザーバブルに追加できます。


エラー処理を考慮していただきありがとうございます。複数のオブザーバブルの場合、エラー処理を理解するのは非常に困難です。
dDeshmane19年

2
私はあなたが何を誤解していると考えているconcat()combineLatest()やっているコード。Array.prototype.concatRxJSconcatメソッドではなく、メソッドのように見えます。私が正しいと仮定すると、この答えは誤解を招き、正しくありcombineLatest()ません。オブザーバブルを1つずつ順番に実行しないからです。と同じように、それらを並行して実行しますforkJoin()。違いは、生成される値の数と、ソースのオブザーバブルが完了する必要があるかどうかです。
GregL

@GregL Array.concatは、オブザーバブルでは無意味です。私はconcatのシーケンシャルな性質に絶対に依存しています。理解しておくべき重要なことは、すべてが実行されるまで出力値を取得しないということです。
Simon_Weaver

私はあなたが投稿したサンプルソースコードでこのコードを参照していました:[source].concat(observables)、それが「combineLatest内部的に使用するconcat」と言ったときの意味であると仮定します。配列concatとRxJSconcatを混同しているように思えます。後者は実際に入力オブザーバブルを順番に実行し、それぞれが完了するまで待機します。しかしcombineLatest()、それはによって使用されません、それは完全に別の演算子です。
GregL

3
私は信じてcombineLatest()おり、forkJoin()両方が並行して実行されます。以下のコードを実行すると、両方で約5000が出力されます。 const start = new Date().getTime(); combineLatest([of(null).pipe(delay(5000)), of(null).pipe(delay(5000)), of(null).pipe(delay(5000))]).subscribe(() => console.log(new Date().getTime() - start)); forkJoin([of(null).pipe(delay(5000)), of(null).pipe(delay(5000)), of(null).pipe(delay(5000))]).subscribe(() => console.log(new Date().getTime() - start));
ジェレミー

13

forkJoin-すべてのオブザーバブルが完了したら、それぞれから最後に発行された値を発行します。

CombineLatest-観測可能なものが値を放出するとき、それぞれから最新の値を放出します。

使用法は非常に似ていますが、forkJoinとは異なり、combineLatestの購読を解除することを忘れないでください 。


1
リクエストが失敗した場合、ネストされたすべてのリクエストが自動的にキャンセルされた場合、どうすればこれを解決できますか?
SunilGarg19年

1
@SunilGargすべての結果のみを取得する場合は、forkJoinまたはcombineLatestを使用する必要があります。すべての結果を気にしない場合は、サブスクリプションを個別に使用する必要があります。
DmitryGrinko19年


コード例で登録解除が必要な理由を説明できますか
SunilGarg20年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.