Angular+NgRx Effects中actions$与服务注入为undefined的问题求助
问题现象
在Angular项目中使用NgRx Effects时,NoteEffects类构造函数中的actions$和noteService被注入为undefined,导致this.actions$.pipe调用失败,抛出以下错误:
TypeError: Cannot read properties of undefined (reading 'pipe')
at note.effects.ts:17:19
at createEffect (ngrx-effects.mjs:85:47)
at <instance_members_initializer> (note.effects.ts:16:16)
at new _NoteEffects (note.effects.ts:11:3)
at Object.NoteEffects_Factory [as factory] (note.effects.ts:61:6)
at core.mjs:3132:35
at runInInjectorProfilerContext (core.mjs:866:5)
at R3Injector.hydrate (core.mjs:3131:11)
at R3Injector.get (core.mjs:3005:23)
at injectInjectorOnly (core.mjs:1095:36)
问题根源
NoteEffects中loadNotes$使用箭头函数初始化,在类成员初始化阶段,构造函数尚未完成依赖注入,此时this未指向完整的类实例,导致访问this.actions$和this.noteService均为undefined。
解决方案
方案1:修正类成员初始化方式(保持类式Effects)
将箭头函数替换为普通函数,或使用Angular的inject函数直接获取依赖(Angular 14+支持):
方式A:使用inject函数获取依赖
修改note.effects.ts:
import { Injectable } from '@angular/core'; import { of } from 'rxjs'; import { catchError, map, mergeMap } from 'rxjs/operators'; import { NoteDetailService } from '../../note-detail.service'; import * as NoteActions from './note.actions'; import { NoteDetail } from '../../note-detail.model'; import { Actions, createEffect, ofType, inject } from '@ngrx/effects'; @Injectable() export class NoteEffects { // 直接通过inject获取依赖,无需构造函数注入 private actions$ = inject(Actions); private noteService = inject(NoteDetailService); loadNotes$ = createEffect(() => this.actions$.pipe( ofType(NoteActions.loadNotes), mergeMap(() => this.noteService.refreshList().pipe( map((notes: NoteDetail[]) => NoteActions.loadNotesSuccess({ notes })), catchError((error) => of(NoteActions.loadNotesFailure({ error }))) ) ) ) ); }
方式B:改用普通函数定义Effect
import { Injectable } from '@angular/core'; import { of } from 'rxjs'; import { catchError, map, mergeMap } from 'rxjs/operators'; import { NoteDetailService } from '../../note-detail.service'; import * as NoteActions from './note.actions'; import { NoteDetail } from '../../note-detail.model'; import { Actions, createEffect, ofType } from '@ngrx/effects'; @Injectable() export class NoteEffects { constructor( private actions$: Actions, private noteService: NoteDetailService ) {} // 使用普通函数,确保this指向类实例 loadNotes$ = createEffect(function(this: NoteEffects) { return this.actions$.pipe( ofType(NoteActions.loadNotes), mergeMap(() => this.noteService.refreshList().pipe( map((notes: NoteDetail[]) => NoteActions.loadNotesSuccess({ notes })), catchError((error) => of(NoteActions.loadNotesFailure({ error }))) ) ) ); }); }
方案2:使用函数式Effects(NgRx 15+推荐)
无需定义类,直接通过函数创建Effect,更简洁且避免this绑定问题:
1. 修改note.effects.ts
import { of } from 'rxjs'; import { catchError, map, mergeMap } from 'rxjs/operators'; import { NoteDetailService } from '../../note-detail.service'; import * as NoteActions from './note.actions'; import { NoteDetail } from '../../note-detail.model'; import { Actions, createEffect, ofType, inject } from '@ngrx/effects'; export const loadNotes$ = createEffect( (actions$ = inject(Actions), noteService = inject(NoteDetailService)) => { return actions$.pipe( ofType(NoteActions.loadNotes), mergeMap(() => noteService.refreshList().pipe( map((notes: NoteDetail[]) => NoteActions.loadNotesSuccess({ notes })), catchError((error) => of(NoteActions.loadNotesFailure({ error }))) ) ) ); }, { functional: true } );
2. 更新main.ts中的Effects配置
// 替换原有的provideEffects([NoteEffects]) provideEffects([loadNotes$]),
额外验证点
- 确认
NoteDetailService的providedIn: 'root'配置正确,确保服务已被Angular注入系统注册。 - 检查
main.ts中provideEffects已正确添加到providers数组。
内容的提问来源于stack exchange,提问作者kimrenny

