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})))
疑问解答
为何仅服务器环境出现该错误,本地却正常?
核心原因是NGRX运行时检查的配置差异:服务器对应的生产环境默认启用了strictActionSerializability严格校验,而本地开发环境通常未开启该检查(或你手动关闭了)。NGRX在生产模式下会自动启用这类严格校验,确保Store中的状态都是可序列化的,避免出现状态不一致的潜在问题。为何类型为any的error不具备可序列化性?
any只是TypeScript的类型标注,不会改变实际传入对象的本质。你传入的error是原生Error实例(或类似的错误对象),这类对象包含不可序列化的属性——比如stack(包含函数调用栈的引用)、原型链上的方法,这些内容无法被JSON序列化。NGRX的严格检查会扫描Action的所有属性,一旦发现不可序列化的内容就会抛出错误。是否有更优的错误传递至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
相关产品推荐
相关产品推荐

