You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NGRX中Effects错误传递至Actions及序列化问题排查

NGRX Action错误序列化问题解答

问题重现

本地环境将Effect抛出的错误通过Action存入Store正常,但部署到服务器后出现以下错误:

Error: Detected unserializable action at "error". https://ngrx.io/guide/store/configuration/runtime-checks#strictactionserializability

相关代码:

Action定义

export const loginFailed = createAction(
  "[Login dialog] User log in failed",
  props<{error : any}>()
);

Effect中的catch逻辑

catchError((error) => of(AuthActions.loginFailed({error : error})))

疑问解答

  1. 为何仅服务器环境出现该错误,本地却正常?
    核心原因是NGRX运行时检查的配置差异:服务器对应的生产环境默认启用了strictActionSerializability严格校验,而本地开发环境通常未开启该检查(或你手动关闭了)。NGRX在生产模式下会自动启用这类严格校验,确保Store中的状态都是可序列化的,避免出现状态不一致的潜在问题。

  2. 为何类型为any的error不具备可序列化性?
    any只是TypeScript的类型标注,不会改变实际传入对象的本质。你传入的error是原生Error实例(或类似的错误对象),这类对象包含不可序列化的属性——比如stack(包含函数调用栈的引用)、原型链上的方法,这些内容无法被JSON序列化。NGRX的严格检查会扫描Action的所有属性,一旦发现不可序列化的内容就会抛出错误。

  3. 是否有更优的错误传递至Store的方案?
    最优方案是仅传递错误的可序列化属性,不要直接传入Error对象:

    • 先定义一个专门的错误载荷类型,只保留前端需要的可序列化字段:
      interface ErrorPayload {
        message: string;
        code?: number;
        name?: string;
      }
      
    • 修改Action的props类型:
      export const loginFailed = createAction(
        "[Login dialog] User log in failed",
        props<{ error: ErrorPayload }>()
      );
      
    • 在Effect的catch中提取错误的可序列化属性:
      catchError((error) => {
        const payload: ErrorPayload = {
          message: error.message || '未知错误',
          code: error.code,
          name: error.name
        };
        return of(AuthActions.loginFailed({ error: payload }));
      })
      

    这样既符合NGRX的序列化要求,也能保留前端业务所需的错误信息。


内容的提问来源于stack exchange,提问作者w00ter

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 18:02:48