NGRX Effect调用API后成功动作触发异常问题求助
NGRX Effects 触发异常问题分析与解决
动作定义
export const createSite = createAction( '[Site] Create Site', props<{ site: SiteRequest }>() ); export const createSiteSuccess = createAction( '[Site] Create Site Success', props<{ site: SiteResponse }>() ); export const createSiteFailed = createAction( '[Site] Create Site Failed', props<{ error: any }>() );
Reducer 代码
export const SITES_FEATURE_KEY = 'sites'; export interface State extends EntityState<SiteResponse> { selectedId?: string | number; loaded: boolean; loading: boolean; error?: string | null; } export interface SitesPartialState { readonly [SITES_FEATURE_KEY]: State; } export const sitesAdapter: EntityAdapter<SiteResponse> = createEntityAdapter<SiteResponse>(); export const initialState: State = sitesAdapter.getInitialState({ loaded: false, loading: false, }); const sitesReducer = createReducer( initialState, on(SitesActions.createSite, (state) => ({ ...state, loaded: false, loading: true, error: null })), on(SitesActions.createSiteSuccess, (state, { site }) => sitesAdapter.addOne(site, { ...state, loaded: true, loading: false}) ), on(SitesActions.createSiteFailed, (state, { error }) => ({ ...state, error, })) ); export function reducer(state: State | undefined, action: Action) { return sitesReducer(state, action); }
Effects 代码(原始错误版本)
@Injectable() export class SiteEffects { createSite$ = createEffect(() => this.actions$.pipe( ofType(SiteActions.createSite), exhaustMap((action) => this.siteService.createSite(action.siteRequest) .pipe( map(site => SiteActions.createSiteSuccess({ site })), catchError((error) => of(SiteActions.createSiteFailed({ error })) ) ) ) ); createSiteSuccess$ = createEffect(() => this.actions$.pipe( ofType(SiteActions.createSiteSuccess), tap(() => this.router.navigate['dashboard']) ), { dispatch: false } ); constructor( private actions$: Actions, private siteService: SiteService, private router: Router, ) {} }
遇到的问题
- 同时保留
createSite$和createSiteSuccess$时,createSite$完全不触发,API调用未执行; - 注释
createSiteSuccess$后,createSite$正常触发,API返回201状态码及site对象,且reducer成功添加实体,但无法跳转仪表盘; - 移除
createSiteSuccess$的dispatch: false配置时,createSite$触发且API执行,但会陷入循环(符合预期,故需保留dispatch: false)。
问题原因与修复方案
错误点1:动作属性访问错误
createSite动作定义的props是{ site: SiteRequest },但createSite$中错误访问了action.siteRequest,导致传入siteService.createSite的参数为undefined,直接触发catchError分支分发失败动作。而createSiteSuccess$只监听成功动作,所以看起来createSite$没触发,实际是触发后直接走到错误流程。
错误点2:路由导航写法错误
this.router.navigate['dashboard']是错误写法,navigate是方法,需调用this.router.navigate(['dashboard'])。该错误会抛出异常,中断Effects执行链,也是导致createSite$看起来未触发的原因之一。
错误点3:RxJS操作符括号未闭合
catchError的of(SiteActions.createSiteFailed({ error }))缺少闭合括号,导致代码语法错误,影响整个Effect的编译与执行。
修复后的Effects代码
@Injectable() export class SiteEffects { createSite$ = createEffect(() => this.actions$.pipe( ofType(SiteActions.createSite), exhaustMap((action) => this.siteService.createSite(action.site) .pipe( map(site => SiteActions.createSiteSuccess({ site })), catchError((error) => of(SiteActions.createSiteFailed({ error }))) ) ) ) ); createSiteSuccess$ = createEffect(() => this.actions$.pipe( ofType(SiteActions.createSiteSuccess), tap(() => this.router.navigate(['dashboard'])) ), { dispatch: false } ); constructor( private actions$: Actions, private siteService: SiteService, private router: Router, ) {} }
额外检查项
- 确认
SiteService.createSite方法正确接收SiteRequest参数,并返回Observable<SiteResponse>; - 确保Effects已在模块中正确注册(如
EffectsModule.forRoot([SiteEffects])); - 开发模式下查看控制台,排查是否有未捕获的语法或运行时错误。
内容的提问来源于stack exchange,提问作者innoveltec
相关产品推荐
相关产品推荐

