タイマーでcatchErrorを続行する方法(rxjs)

Aug 23 2020

タイマーを使用して、x秒ごとにhttpClient.getを実行するサービスがあります。サービスが起動するたびにこのタイマーの実行を開始する必要があるため、タイマーサービス コンストラクターで定義されます。私の理解によると、サブスクリプションは以下のようにタイマースコープに登録する必要があります(正しくない場合を除いて、必要がなければ変更したくありません)。

バックエンドサーバーからのerrors \ exceptions \ error 500例外がない限り、すべてのシステムは正常に動作しています。今、私は2つのものが必要です:

  1. バックエンドサーバーに問題があるときはいつでもCatchErrorをしたいと思います。
  2. 例外があっても、オブザーバーはタイマー時間(次のティックまで)に従って実行し続けてほしい。私の最終結果は、例外があるときはいつでもコンポーネントの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();