こんにちは私は次のコードを持っています。エラーがスローされたときにメイン(アップストリーム)Observableが削除されないようにする方法を知りたいです。
すべての数値が「4」を期待するように次のコードを変更するにはどうすればよいですか?
さまざまな演算子で他のケースで機能する一般的なパターンソリューションを探しています。これは私が思いつくことができる最も単純なケースです。
const Rx = require('rxjs/Rx');
function checkValue(n) {
if(n === 4) {
throw new Error("Bad value");
}
return true;
}
const source = Rx.Observable.interval(100).take(10);
source.filter(x => checkValue(x))
.catch(err => Rx.Observable.empty())
.subscribe(v => console.log(v));
ソースオブザーバブルを実行したままにする必要がありますが、メインイベントストリームでエラーを発生させると、オブザーバブル全体が折りたたまれ、アイテムを受信できなくなります。
解決策は、上流のパイプを崩さずにフィルター処理およびキャッチできる分離されたストリームを作成することです。
_const Rx = require('rxjs/Rx');
function checkValue(n) {
if(n === 4) {
throw new Error("Bad value");
}
return true;
}
const source = Rx.Observable.interval(100).take(10);
source
// pass the item into the projection function of the switchMap operator
.switchMap(x => {
// we create a new stream of just one item
// this stream is created for every item emitted by the source observable
return Observable.of(x)
// now we run the filter
.filter(checkValue)
// we catch the error here within the projection function
// on error this upstream pipe will collapse, but that is ok because it starts within this function and will not effect the source
// the downstream operators will never see the error so they will also not be effect
.catch(err => Rx.Observable.empty());
})
.subscribe(v => console.log(v));
_
また、catchセレクターに渡された2番目の引数を使用して、監視可能なソースを再起動することもできますが、これにより、以前に実行されていないかのように起動されます。
_const Rx = require('rxjs/Rx');
function checkValue(n) {
if(n === 4) {
throw new Error("Bad value");
}
return true;
}
const source = Rx.Observable.interval(100).take(10);
source.filter(x => checkValue(x))
.catch((err, source) => source)
.subscribe(v => console.log(v));
_
しかし、これでは望ましい効果が得られません。時間の終わりまで1..3を繰り返し放出するストリームが表示されます...またはスクリプトをシャットダウンします。いずれか早い方。 (これは.retry()
の機能に不可欠です)
フィルタリングを行う場所では、flatMapオペレーターを使用する必要があります。この例のflatMapでは、Observable.if()を使用してフィルタリングを行っています。これにより、常に監視可能オブジェクトが返されることが保証されます。他の方法でもできると思いますが、これは私にとってクリーンな実装です。
const source = Rx.Observable.interval(100).take(10).flatMap((x)=>
Rx.Observable.if(() => x !== 4,
Rx.Observable.of(x),
Rx.Observable.throw("Bad value"))
.catch((err) => {
return Rx.Observable.empty()
})
);
source.subscribe(v => console.log(v));