要するに:すべての_.catch
_の前に_.subscribe
_を置くことなく、ストリームのエラーの後にリスニングを続行するにはどうすればよいですか?
詳細が必要な場合は、こちらをご覧ください。
現在のユーザーのサブジェクトまたはnullがあると仮定します。 APIからデータを取得して、サブジェクトに送信することがあります。それに応じてビューを更新します。しかし、ある時点でサーバーでエラーが発生し、アプリケーションを以前と同じように動作させ続けたいのですが、エラーについていくつかの場所に通知し、件名をリッスンし続けます。
当初、userSubject.error(...)
を実行すると、サブスクライブ時に_.catch
_コールバックとerror
ハンドラーのみがトリガーされ、すべての成功ハンドラーとチェーンがスキップされると思いました。そして、userSubject.next(...)
を呼び出した後、すべてのチェーンとサブスクライバーは以前と同じように機能します
しかし、残念ながらそうではありません。最初に捕捉されなかった_.error
_の後、サブスクライバーはストリームからサブスクライブ解除され、サブスクライバーは動作しなくなります。
だから私の質問:なぜですか?また、null
値を通常どおり処理したいが、一部の場所でのみエラーを処理したい場合は、代わりにどうすればよいですか?
サブスクライバーがエラーでサブスクライブを解除するRxJsソースコードへのリンクは次のとおりです https://github.com/ReactiveX/rxjs/blob/master/src/Subscriber.ts#L14
Rx
observables 文法に従うnext*(error|complete)?
、つまり、error
またはcomplete
通知が配信された後は何も生成できません。
これが重要である理由の説明は Rx設計ガイドライン から見つけることができます:
監視可能なシーケンスが終了したことを示す単一のメッセージにより、監視可能なシーケンスのコンシューマーは、クリーンアップ操作を安全に実行できることを決定論的に確立できます。
さらに、単一障害により、複数の監視可能なシーケンスで動作する演算子のアボートセマンティクスを維持できます。
つまり、サーバーエラーが発生した後もオブザーバーがサブジェクトをリッスンし続けるようにしたい場合は、そのエラーをサブジェクトに配信せず、他の方法で処理します(たとえば、catch
、retry
または専用のサブジェクトにエラーを配信します)。
すべてのObservableは、0個以上のnext
通知と1個のerror
またはcomplete
を発行しますが、両方を発行することはありません。
このため、サブジェクトには内部状態があります。
次に、チェーンをどのように構築するかによって異なります。たとえば、retry()
を使用して、エラー時にそのソースObservableに再サブスクライブできます。
または、サブジェクトに値を渡す場合、next
通知のみを送信し、他の2つは無視できます。
.subscribe(v => subject.next(v));
または、ユーザーがnull
のときにエラーをスローする場合は、例外をキャプチャしてエラー通知として送信する任意の演算子を使用できます。たとえば、次のようになります。
.map(v => {
if (v === null) {
throw new Error("It's broken");
}
return v;
})
とにかく、コードなしでより正確なアドバイスを与えるのは難しいです。