次のコードでは、1 つの値を生成してから完了する単純なオブザーバブルを作成します。次に、最後のアイテムを再生し、3 回サブスクライブすることを共有します。1 回目は直後、2 回目は値が生成される前、3 回目は値が生成されてオブザーバブルが完了した後です。
let i = 0;
let obs$ = Rx.Observable.create(obs => {
console.log('Creating observable');
i++;
setTimeout(() => {
obs.onNext(i);
obs.onCompleted();
}, 2000);
}).shareReplay(1);
obs$.subscribe(
data => console.log(`s1: data = ${data}`),
() => {},
() => console.log('finish s1')
);
setTimeout( () => {
obs$.subscribe(
data => console.log(`s2: data = ${data}`),
() => {},
() => console.log('finish s2')
);
}, 1000);
setTimeout( () => {
obs$.subscribe(
data => console.log(`s3: data = ${data}`),
() => {},
() => console.log('finish s3')
);
}, 6000);
これをjsbinで実行できます
これにより、次の大理石図が得られます
Actual
s1: -----1$
s2: \--1$
s3: \1$
しかし、私は期待します
Expected
s1: -----1$
s2: \--1$
s3: \----2$
誰かが最初の動作をしたい理由は理解できますが、私の理由は、この例とは異なり、数値を返す場合とは異なり、データベース接続など、サブスクライブ解除動作の影響を受けやすいオブジェクトを返す可能性があるからです。上記のマーブル ダイアグラムがデータベース接続を表している場合、dispose メソッドで を呼び出しますdb.close()
。3 番目のサブスクリプションでは、解放されたデータベース ハンドラーを値として受け取っているため、例外が発生します。(2 番目のサブスクリプションが終了すると refCount = 0 になり、ソースが破棄されるため)。
また、この例のもう 1 つの奇妙な点は、最初の値で解決され、その直後に完了し、ソースを 2 回サブスクライブしていることです (複製された「Creating observable」でわかるように)。
このgithubの問題がこれについて話していることは知っていますが、欠けているのは次のとおりです。
ソースオブザーバブルが完了していない場合に最後のアイテムを再生できる共有オブザーバブルをどのように達成できますか (refCount = 0)、オブザーバブルを再作成します。
RxJs5 では、share メソッドが問題の再接続部分を解決すると思いますが、共有部分は解決しません。
RxJs4では私は無知です
可能であれば、既存の演算子またはサブジェクトを使用してこれを解決したいと考えています。私の直感では、そのようなロジックを使用して別のサブジェクトを作成する必要があることがわかりますが、まだそこまで進んでいません。