🖌️
ngxs
  • 介绍
  • 入门
    • 为什么使用ngxs
    • 安装
  • 概念
    • 介绍
    • 存储(Store)
    • 动作(Actions)
    • 状态(State)
    • 选择(Select)
  • 高级
    • 动作处理程序
    • 动作的生命周期
    • 取消
    • 组合
    • 错误处理
    • Ivy迁移指南
    • 延迟加载
    • 生命周期
    • 映射子状态
    • 元归约器
    • 优化选择器
    • 选项
    • 共享状态
    • 状态令牌
    • 状态操作
    • 子状态
  • 菜单
    • 认证
    • 缓存
    • NGXS的组件事件
    • 防抖动动作
    • 动态插件
    • 不可变数据助手
    • 设计指南
    • 单元测试
  • 插件
    • 介绍
    • CLI
    • Logger
    • Devtools
    • Storage
    • Forms
    • Web Socket
    • Router
    • HMR
  • NGXS实验室
    • 介绍
  • 社区
    • FAQ
    • 资源
    • 贡献者
    • 贡献
    • 赞助商
  • 变更日志
Powered by GitBook
On this page
  • Handling errors within an @Select
  • Why does RxJS unsubscribe on error?
  • Handling errors within an @Action
  • Handling errors after dispatching an action

Was this helpful?

  1. 高级

错误处理

NGXS uses Angular's default ErrorHandler class, so if an action throws an error, Angular's ErrorHandler is called. You can easily override this flow by providing your own handler like so:

import { NgModule, ErrorHandler } from '@angular/core';

@Injectable()
export class MyErrorHandler implements ErrorHandler {
  handleError(error: any) {
    console.log('ERROR! ', error);

    // Make sure to rethrow the error so Angular can pick it up
    throw error;
  }
}

@NgModule({
  imports: [AppComponent],
  providers: [
    {
      provide: ErrorHandler,
      useClass: MyErrorHandler
    }
  ]
})
export class AppModule {}

Handling errors within an @Select

@Component({ ... })
class AppComponent {
  @Select(state => state.count.number.value) count$: Observable<number>;
}

Let's take a look at the below example:

this.store.reset({}); // reset all states

The catch is that when resetting the entire state, the object will no longer have those deeply nested properties (state.count.number.value). Given the following code:

const state = {};

function getCount() {
  return state.count.number.value;
}

const count = getCount(); // will throw

RxJS will automatically complete the stream under the hood if any error is thrown.

You have to disable suppressing errors using the suppressErrors option:

@NgModule({
  imports: [
    NgxsModule.forRoot([CountState], {
      selectorOptions: {
        suppressErrors: false // `true` by default
      }
    })
  ]
})
export class AppModule {}

This option allows to track errors and handle them.

@Component({ ... })
class AppComponent {
  @Select(state => {
    try {
      return state.count.number.value;
    } catch (error) {
      console.log('error', error);
      // throw error;
      // Automatic unsubscription will occur if you use the `throw` statement here. Skip it if you don't want the stream to be completed on error.
    }
  })
  count$: Observable<number>;
}

Why does RxJS unsubscribe on error?

Handling errors within an @Action

When you define an @Action you can handle error within the action and if you do so, the error will not propagate to Angular's global ErrorHandler, nor the dispatch Observable. This applies to both sync and async types of Actions.

  @Action(HandledError)
  handledError(ctx: StateContext<StateModel>) {
    try {
      // error is thrown
    } catch (err) {
      console.log('error catched inside @Action wont propagate to ErrorHandler or dispatch subscription')
    }
  }

Handling errors after dispatching an action

If an unhandled exception is thrown inside an action, the error will be propagated to the ErrorHandler and you can also catch it subscribing to the dispatch Observable. If you subscribe to the dispatch Observable the error will be caught twice, once in the ErrorHandler and on your dispatch handle.

  @Action(UnhandledError)
  unhandledError(ctx: StateContext<StateModel>) {
    // error is thrown
  }
  unhandled() {
    this.store.dispatch(new UnhandledError()).pipe(
      catchError(err => {
        console.log('unhandled error on dispatch subscription')
        return of('')
      })
    ).subscribe();
  }

It is recommended to handle errors within @Action and update state to reflect the error, which you can later select to display where required.

Previous组合NextIvy迁移指南

Last updated 4 years ago

Was this helpful?

RxJS provides a great explanation of this behavior.

You can play around with error handling in this following

design guidelines
stackblitz