タイマーでcatchErrorを続行する方法(rxjs)
Aug 23 2020
タイマーを使用して、x秒ごとにhttpClient.getを実行するサービスがあります。サービスが起動するたびにこのタイマーの実行を開始する必要があるため、タイマーはサービス コンストラクターで定義されます。私の理解によると、サブスクリプションは以下のようにタイマースコープに登録する必要があります(正しくない場合を除いて、必要がなければ変更したくありません)。
バックエンドサーバーからのerrors \ exceptions \ error 500例外がない限り、すべてのシステムは正常に動作しています。今、私は2つのものが必要です:
- バックエンドサーバーに問題があるときはいつでもCatchErrorをしたいと思います。
- 例外があっても、オブザーバーはタイマー時間(次のティックまで)に従って実行し続けてほしい。私の最終結果は、例外があるときはいつでもコンポーネントのpopUpAlertに到達するはずです私のコードを参照してください-これはwebapiコントローラーです:
public IActionResult getSomeErrorAsTest()
{
try
{
throw new Exception("Serer error");
}
catch(Exception ex)
{
return StatusCode(StatusCodes.Status500InternalServerError, new List<string>());
//throw ex;
}
}
これはサービスです(すべてのgetリクエストでデータが変更されると想定します-実際に変更する場合は実装する必要はありません):
export class MyService
{
MyDataSubject = new Subject<any[]>();
MyDataChanged :Observable>any[]> = this.MyDataSubject.asObservable();
subscribe :Subscription;
constructor(private httpClient : HttpClient)
{
this.subscribe = timer(0, 30000).pipe(
switchMap(()=>
this.getData())).subscribe();
}
getData()
{
return this.httpClient.get<any[]>(<controller url>)
.pipe(
tap(res =>
{
this.MyDataSubject.next(res);
}),
catchError(error =>
{
debugger;//I would expect to catch the debugger here, but nothing happens
return throwError(error);
})
)
}
}
消費者コンポーネント:
export class MyComponent (private mySrv : MyService)
{
getMyData()
{
let sub =this.mySrv.MyDataChanged.subscribe(result => doSomething(),
error=> popUpAlert());
}
}
回答
2 RafiHenig Aug 23 2020 at 18:42
CatchError
演算子はエラーの処理を許可しますが、observableの性質は変更しません-エラーは特定のobservableの最終条件であるため、放出は停止します。CatchError
オブザーバーのエラーコールバック(metasong)を発生させる代わりに、発生時にdesires値を発行できます。![]()
以下に示すように、内部のObservable(つまり内部switchMap
)でエラーを処理して、そこで発生したエラーがメインストリームにバブルアップしないようにします。これにより、エラーが発生した後もメインストリームが続行されます。
this.subscribe = timer(0, 30000)
.pipe(
switchMap(() => this.getData().pipe(catchError(x => of("handle error here"))))
// catchError(...) don't handle error here
)
.subscribe();