【问题标题】:Is there a way to deal with error handling in a Async pipe in such a way that my GlobalErrorHandler does not pick up this error?有没有办法处理异步管道中的错误处理,使我的 GlobalErrorHandler 不会接收到这个错误?
【发布时间】:2021-10-03 11:43:39
【问题描述】:

我正在为我的 GlobalErrorHandler 和组件模板中的 Async 管道苦苦挣扎。

在UserprofilesViewComponent的模板中:

<h2>Userprofiles</h2>
<ng-container *ngIf="userprofiles$ | async; else fail">
  <app-userprofile-list [userprofiles$]="userprofiles$"></app-userprofile-list>
</ng-container>

<ng-template #fail>
  <ng-container *ngIf="errorMessage$ | async as errorMessage">
    <h3>{{errorMessage}}</h3>
  </ng-container>
</ng-template>

在 UserprofilesViewComponent 的 ngOnInit() 中:

// ...
this.userprofiles$ = this.userprofileService.getUserprofiles()
    .pipe(
      catchError((err:AppError) => {
      this.errorMessage$ = of(err.error.message);
      // return throwError(err);  // Error will propagate and be picked up by my GlobalErrorHandler
      return of([]);  // No erroring out, so no error picked up by my GlobalErrorHandler
    }),
    );

顺便说一句,我有一个 HTTPInterceptor,它将所有 HttpErrorResponse 转换为 AppError,用于我的应用程序中的所有数据服务。因此,所有服务都接收 AppError 对象而不是 HttpErrorResponse。

问题:

如果我在 catchError throwError(err) 中重新抛出错误,那么订阅 userprofiles$ 的异步管道将出错。正如代码中所预期的那样,将触发 else 分支('fail'-template)进行显示(也不会显示呈现用户配置文件列表的模板 --> 这是我的意图)。一切都按我的计划执行,但我的 GlobalErrorHandler 也被触发以处理抛出的错误 (throwError)。我不想触发全局错误处理程序。

如果我替换of([]) 作为对发生错误的响应,模板中的else branch 将不会被触发,因为没有错误(而是空列表的后备结果)。但是,随后将呈现用户配置文件列表,并且页面上不会显示任何错误消息。这不是我想要的行为。在这种情况下,我的全局错误处理程序都不会被触发,因为显然没有抛出任何错误(捕获替换模式)。

简而言之:

我试图弄清楚如何阻止async 导致这种情况。 AFAIK,当 async 管道应用于可观察的 userprofiles$, it will subscribe and therefore will detect/trigger the thrownError. But apparently at this point in the template an unhandled error will occur and will bubble up` 时,直到我注册的 GlobalErrorHandler 将选择错误并处理它。我不希望这种情况发生。所以我正在寻找一种方法让 GlobalErrorHandler 不处理这个错误。

这种情况有什么规律吗?

【问题讨论】:

    标签: angular


    【解决方案1】:

    假设您通过实现ErrorHandler 接口来使用自定义全局错误处理程序。

    您的GlobalErrorHandler 将拦截所有全局异常 出现在您的代码中。

    即使您尝试返回一个立即出错的新 Observable,您的 GlobalErrorHandler 仍然会捕获它。

    this.userprofiles$ = this.userprofileService.getUserprofiles()
        .pipe(
          catchError((err:AppError) => {
          this.errorMessage$ = of(err.error.message);
          return new Observable((subscriber) => subscriber.error(err));  // Error will still propagate 
        }),
        );
    

    解决方案: 在您的catchError 中使用 return of([]); & 稍微重构一下你的 HTML。异步管道完成后检查数组长度:

    <h2>Userprofiles</h2>
    <ng-container *ngIf="userprofiles$ | async as userList;">
      <app-userprofile-list *ngIf="userList && userList.length>0;else fail" [userprofiles$]="userprofiles$"></app-userprofile-list>
    </ng-container>
    
    <ng-template #fail>
      <ng-container *ngIf="errorMessage$ | async as errorMessage">
        <h3>{{errorMessage}}</h3>
      </ng-container>
    </ng-template>
    

    【讨论】:

      猜你喜欢
      • 2016-11-08
      • 1970-01-01
      • 2017-09-18
      • 2019-04-12
      • 2014-02-27
      • 2021-02-14
      • 1970-01-01
      • 2018-12-31
      • 1970-01-01
      相关资源
      最近更新 更多