【问题标题】:Handling errors in NGXS (angular) with global error handler使用全局错误处理程序处理 NGXS(角度)中的错误
【发布时间】:2019-11-14 06:56:42
【问题描述】:

我想以两种方式处理 NGXS 中的错误。第一种方法是在组件中处理 store dispatch 的错误。第二种方式是全局角度错误处理程序,作为未处理错误(第一种方式未处理)时的后备。

但问题是,当动作处理程序出现错误时,NGRX 总是调用全局错误处理程序。

所以在组件中给出这段代码:

this.store.dispatch(new FetchAction())
   .subscribe( error: () => console.log('fetch error occured'))

这个动作处理程序:

fetch() {
   return this.http.get('..');
}

还有这个全局错误处理程序:

export class GlobalErrorHandler extends ErrorHandler {
   handleError(err: any) {
      console.log('unexpected error occured');
   }
}

控制台中会有两条错误消息。一个来自调度的订阅,另一个来自全局错误处理程序,因为操作处理程序中存在错误。

现在我可以在动作处理程序中捕获错误,但这样做是错误的,因为动作处理程序不应该知道该动作的错误是在组件中处理的。

我做了一个堆栈闪电战,当单击按钮时在控制台中显示两个错误:https://stackblitz.com/edit/ngxs-error-throw-r42fkb?file=src/app/app.component.ts

【问题讨论】:

  • 您好,我推荐您学习 Angular 拦截器:scotch.io/@vigneshsithirai/…
  • 我确实知道 http 拦截器,但这不是解决方案。 http拦截器仍然必须返回结果。您显然无法在此处捕获错误并告诉应用程序响应成功并返回一些值(甚至会是什么?),而实际上它根本不成功。它仅在没有全局错误处理程序时才有效。但是应该一直支持全局错误处理程序,因为它是 angular 的一个组成部分
  • 创建了一个新的堆栈闪电战,重现了该问题:stackblitz.com/edit/…希望有人能提供帮助。
  • 您找到解决方案了吗?我也有同样的问题。

标签: angular ngxs


【解决方案1】:

我也有同样的问题。但正如文档所说,这是设计使然。尽管您在上层处理,但错误正在传播到主 ErrorHandler。

如果在动作中抛出未处理的异常,错误将被传播到 ErrorHandler 并且您也可以通过订阅调度 Observable 来捕获它。如果您订阅了 dispatch Observable,错误将被捕获两次,一次是在 ErrorHandler 中,一次是在您的 dispatch 句柄上

【讨论】:

    【解决方案2】:

    使用 RxJS catchError 操作符处理底层错误:

    这样,您捕获了错误,因此它不会调用您的全局操作处理程序。

    this.store.dispatch(new FetchAction())
       .pipe(catchError(error => /* Do something specific with the error. */))
       .subscribe(() => { /* Do something with the success result. */ })
    

    让错误冒泡到全局操作处理程序:

    这里没什么特别的。只需忽略错误。 当您不知道如何处理错误时,请执行此操作。

    this.store.dispatch(new FetchAction())
       .subscribe(() => { /* Do something with the success result. */ })
    

    如果需要,您可以使用 throwError 重新抛出更具体的错误,以便在更高级别处理它时获得更多信息。

    this.store.dispatch(new FetchAction())
       .pipe(catchError(error => throwError(new Error('Some specific error.'))))
       .subscribe(() => { /* Do something with the success result. */ })
    

    【讨论】:

    • "这样,您就发现了错误,因此它不会调用您的全局操作处理程序。"我猜你的意思是全局错误处理程序。但这正是重点。当 ngxs 操作处理程序中出现错误时,这仍将调用全局错误处理程序。如果你没有 catchError 而只是订阅了全局错误处理程序,实际上将被调用两次。
    • 我不知道是什么原因造成的,也许您可​​以在自定义全局错误处理程序中使用Subject 类型与distinctUntilChangeddebounceTime 一起忽略重复项。
    • 是的,这就是我正在使用的,但显然这并不理想。也解决不了问题。当我调度一个动作时,订阅它并使用 catchError 我想我可以明确地处理这个错误。但仍会调用全局错误处理程序。因此,不可能将全局错误处理程序作为后备,仅在我不处理调度错误时调用
    猜你喜欢
    • 2019-10-12
    • 2013-03-06
    • 2023-04-04
    • 1970-01-01
    • 2012-08-11
    • 2016-08-18
    • 2019-05-21
    • 2015-08-04
    • 1970-01-01
    相关资源
    最近更新 更多