【问题标题】:How to continue catchError in timer (rxjs)如何在计时器中继续 catchError (rxjs)
【发布时间】:2020-08-23 10:20:21
【问题描述】:

我有一个服务负责使用计时器每隔 x 秒执行一次 httpClient.get。 我需要这个计时器在服务启动时开始运行,所以 timer 是在 service constructor 中定义的。根据我的理解,订阅应该注册在timer范围内,如下图(没必要我不想改,除非写错了)。

只要后端服务器没有错误\异常\错误500异常,所有系统都可以正常工作。 现在,我需要两件事:

  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());
    }
}

【问题讨论】:

  • 我会将整个错误处理转移到服务中。在您的服务中调用popUpAlert() in catchError 并返回of(null)。当结果为null 但没有错误情况时,让您的组件处理这种情况。在这里查看我的答案:stackoverflow.com/a/54790621/9423231
  • 1) MyDataSubject 不知道抛出了任何错误。因为它在另一个流中抛出 2)您无法捕获 throwError 运算符抛出的错误。它不会导致错误,而是会发出一个值。
  • 与您的问题无关(Rafi 的回答一针见血),但 Angular 中的服务支持一些与组件相同的生命周期回调(包括 OnInit 和 OnDestroy)。您最好在 init 挂钩中启动计时器并在 destory 挂钩中销毁订阅。

标签: angular timer rxjs rxjs-observables rxjs-pipe


【解决方案1】:

CatchError 运算符允许处理错误,但不会改变 observable 的性质 - 错误是给定 observable 的终止条件,因此发射将停止。 CatchError 允许在发生时发出期望值,而不是引发观察者的错误回调 (metasong)。

您可能希望处理内部 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();

【讨论】:

  • 感谢您的详尽回答。我没有达到 HTTP_INTERCEPTORS 的 catchError 原因
猜你喜欢
  • 1970-01-01
  • 2020-02-26
  • 2019-11-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-12
  • 2019-10-01
  • 1970-01-01
相关资源
最近更新 更多