一方では、時々エラーをスローするストリームがあります:
_this.behaviorSubject.error(error)
_
ただし、後で、ストリームを続行します。
_this.behaviorSubject.next(anotherValue)
_
一方、behaviorSubject.asObservable()
にサブスクライブしているサブスクライバーがあります。
サブスクリプションでは、値とエラーを処理しています。
_.subscribe(
( value ) => { /* ok */ },
( error ) => { /* some error */ }
);
_
エラーが発生するたびにonSuccess
が呼び出され、将来のonError
の呼び出しを妨げない、単純なonError
およびonSuccess
コールバックと同じ効果が必要です。作られています。 RXJSでこれを行うにはどうすればよいですか?
私はキャッチを調べましたが、サブスクライバーでエラーが呼び出されるのを防ぐだけのようです。
短い答え:それは不可能です。
これの使用方法: RxJSの基本概念は、error
またはcomplete
- callが基本的に"kill"になることです。ストリーム。この概念により、強制的に"必要に応じてエラーをあちこちに投げるだけ"ではなく、アプリケーション内のエラーとデータの流れを適切に処理します。たとえば、BehaviorSubject
は通常、データを保持するためのものですが、 not を使用して、そのデータを取得/作成し、発生する可能性のあるエラーを処理するプロセスも含める必要がありますデータの取得中。
本を読むにしたい場合は、フローを2つの部分に分割する必要があります:
例として、データフローは次のようになります(概略図として)。
store.ts
dataStore: BehaviorSubject<IData> = new BehaviorSubject<IData>();
errorMessage: BehaviorSubject<IErrorMsg> = new BehaviorSubject<IErrorMsg>();
data-retrieval.ts
fetchDataById(id: string) {
httpService.get(`some/rest/endpoint/${id}`)
.subscribe(handleData, handleError);
}
handleData(data: IData) {
errorMessage.next(null);
dataStore.next(data);
}
handleError(error: Error) {
errorMessage.next(error.message);
dataStore.next(null);
}
"しかし、これは多くのオーバーヘッドのように見えます..."-True、ただし、アプリケーション内のデータのクリーンで理解しやすいフローを保証し、テストと保守が容易です。 ngrx や redux のようなすぐに使用できるストアコンセプトもあります。
Rxは基本的に、オブザーバブルがアクティブまたはファイナライズされる(onCompleteまたはonError)という概念に基づいて構築されています。 Observableがファイナライズしているとき、上流のObservableからサブスクライブを解除します。 _.catch
_はその動作を修正できません。エラーを他の何かにマッピングするオプションのみを提供します。
_Rx.Observable.interval(500)
.mergeMap(i => i % 3 == 2 ? Rx.Observable.throw(new Error('kboom')) : Rx.Observable.of(i))
.catch(err => Rx.Observable.of(err.message))
.subscribe(
val => console.log('val: ' + val),
err => console.log('err: ' + err),
() => console.log('stream completed')
)
_
この例は、5回ではなく3回の排出後に完了することに注意してください。
this.behaviorSubject.error(error)
を呼び出すと、サブジェクトに含まれるObservableを内部的に確定します。何らかの方法でエラーを発生させたい場合は、エラーを非エラー値にする必要があります。
_this.behaviorSubject.next({ value: 'somevalue' });
this.behaviorSubject.next({ error: error });
this.behaviorSubject.next({ value: 'somevalue' });
_
その後、放出された値のプロパティに基づいて、実行するアクションを区別できます。
これはあなたの状況ではうまくいかないかもしれませんが、Angular 2で作業するときにこの同じ問題に遭遇しました。なぜなら、画面間をナビゲートし、サービスがAPI関数がコンストラクターで呼び出され、エラー関数がまだ準備ができていないUIを更新しようとするため、実際には大きな問題が発生します。
私がやったことはうまく動作し、かなりきれいであるようです。エラーハンドラーで件名のリセットを作成しました。
subject.subscribe(
( value ) => { /* ok */ },
( error ) => {
//handle error
//reset subject
this.subject = new Subject<any>();
}
);
これは、画面に移動するたびに新しいサブスクリプションが古い画面から破棄され、新しい画面で設定されるため、新しいサブジェクトが何も傷つけないため、これが機能します。