开发者问题收集

在 Observable.interval() 中捕获 http 错误

2019-02-06
522

我有一段代码,每小时运行一次到给定的 URL。基本上,现在如果 URL 未找到或通常响应错误 500,我就会收到错误消息。该应用程序使用服务工作者,但如果提供的 URL 存在(404/500 触发以下消息),则工作正常:

Failed to load resource: net::ERR_INVALID_RESPONSE
ERROR Error: Uncaught (in promise): TypeError: Failed to register a ServiceWorker: An unknown error occurred when fetching the script.
TypeError: Failed to register a ServiceWorker: An unknown error occurred when fetching the script.
    at resolvePromise (zone.js:831)
    at eval (zone.js:741)
    at eval (zone.js:757)
    at ZoneDelegate.invoke (zone.js:391)
    at Object.onInvoke (core.js:4760)
    at ZoneDelegate.invoke (zone.js:390)
    at Zone.run (zone.js:150)
    at eval (zone.js:889)
    at ZoneDelegate.invokeTask (zone.js:423)
    at Object.onInvokeTask (core.js:4751)

在我的控制台中。我如何优雅地捕获错误?

Observable.interval(3000)
      .subscribe((data) => {
         this.http.get('http://localhost:87887/profile/1/') // doesnt exist
           .subscribe((data) => {
             this.pingStream.next(true);
           },
           err => {

             if (err.status == 500){
              this.pingStream.next(false);
             }
             else{
               this.pingStream.next(true);
             }

           }
           );
      });
2个回答

您应该将订阅逻辑与异步逻辑分开。

Observable.interval(3000)
      .pipe(
       mergeMap(() => make http call),
       catchError( e => this.pingStream.next(false)),
       map((data) => this.pingStream.next(true))
      )
      .subscribe();

mergemap 将每 3 秒进行一次间隔,并对您想要的任何服务进行 http 调用。 catchError 将为您妥善处理该错误 map 将接受成功的调用并使用该值执行某些操作。 subscribe() 仅激活可观察对象。

Mike Tung
2019-02-06

如果您希望链在错误发生后继续,因此 interval(3000) 会继续发出,您必须将 catchError 放在 concatMap 内(或者 mergeMap 也可以)。然后,这取决于您在发生错误时想要做什么。您可以通过返回 EMPTY 来忽略它,或者将其转换为 next 通知:

import { EMPTY } from 'rxjs';
...

// Assuming you're using RxJS 6
interval(3000).pipe(
  concatMap(() => this.http.get('http://localhost:87887/profile/1/').pipe(
    catchError(error => {
      if (err.status == 500){
        this.pingStream.next(false);
      } else {
        this.pingStream.next(true);
      }
      return EMPTY;
    })
  ))
).subscribe(data => this.pingStream.next(true));
martin
2019-02-06