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

Angular18+NGRX18中构造函数注入actions$失效问题

问题

使用Angular 18和NGRX 18时,尝试通过构造函数将actions$注入到Effect中无法正常工作,但改用inject()方法注入则一切正常。

代码示例

import { inject, Injectable } from "@angular/core";
import { Actions, createEffect, ofType } from "@ngrx/effects";
import { actionsList } from "./students.actions";
import { catchError, exhaustMap, map, of } from "rxjs";
import { StudentsRecordsService } from "../services/students-records.service";

@Injectable()
export class StudentsRecordsEffects {
  // actions$ = inject(Actions);
  // studentsRecordsService = inject(StudentsRecordsService);

  loadStudentsRecords$ = createEffect(() => this.actions$.pipe(
    ofType(actionsList.callStudentsRecordsApi),
    exhaustMap(() => this.studentsRecordsService.getStudentsRecords().pipe(
      map(studentsRecords => {
        console.log('API Response:', studentsRecords); // Debug API Response
        return { type: actionsList.callStudentsRecordsApiSuccess, payload: studentsRecords }
      }),
      catchError((error) => {
        console.error('Error fetching students records:', error); // Debug Error
        return of({ type: '[Students API] Students Loaded Error' });
      }),
    ))
  ));

  constructor(
    private actions$: Actions,
    private studentsRecordsService: StudentsRecordsService
  ) {}
}

控制台报错

main.ts:6 TypeError: Cannot read properties of undefined (reading 'pipe')
    at students.effects.ts:12:59
    at <instance_members_initializer> (students.effects.ts:12:26)
    at new _StudentsRecordsEffects (students.effects.ts:26:3)
    at Object.StudentsRecordsEffects_Factory [as factory] (students.effects.ts:31:3)

原因分析

类成员变量的初始化顺序早于构造函数执行。loadStudentsRecords$作为类的属性,会在构造函数注入actions$和studentsRecordsService之前被初始化,此时this.actions$还是undefined,调用pipe()自然会抛出错误。

而inject()方法属于Angular的依赖注入运行时API,它可以在类的成员初始化阶段直接获取依赖,不需要等待构造函数执行,所以能正常拿到Actions实例。

解决方案

方案1:移到构造函数内初始化

如果坚持使用构造函数注入,需要把loadStudentsRecords$的初始化逻辑移到构造函数内部,确保依赖已经注入完成后再创建Effect:

import { inject, Injectable } from "@angular/core";
import { Actions, createEffect, ofType } from "@ngrx/effects";
import { actionsList } from "./students.actions";
import { catchError, exhaustMap, map, of } from "rxjs";
import { StudentsRecordsService } from "../services/students-records.service";

@Injectable()
export class StudentsRecordsEffects {
  loadStudentsRecords$;

  constructor(
    private actions$: Actions,
    private studentsRecordsService: StudentsRecordsService
  ) {
    this.loadStudentsRecords$ = createEffect(() => this.actions$.pipe(
      ofType(actionsList.callStudentsRecordsApi),
      exhaustMap(() => this.studentsRecordsService.getStudentsRecords().pipe(
        map(studentsRecords => {
          console.log('API Response:', studentsRecords);
          return { type: actionsList.callStudentsRecordsApiSuccess, payload: studentsRecords }
        }),
        catchError((error) => {
          console.error('Error fetching students records:', error);
          return of({ type: '[Students API] Students Loaded Error' });
        }),
      ))
    ));
  }
}

方案2:使用inject()注入(推荐)

这是Angular 14+官方推荐的注入方式,代码更简洁,无需考虑初始化顺序问题:

import { inject, Injectable } from "@angular/core";
import { Actions, createEffect, ofType } from "@ngrx/effects";
import { actionsList } from "./students.actions";
import { catchError, exhaustMap, map, of } from "rxjs";
import { StudentsRecordsService } from "../services/students-records.service";

@Injectable()
export class StudentsRecordsEffects {
  actions$ = inject(Actions);
  studentsRecordsService = inject(StudentsRecordsService);

  loadStudentsRecords$ = createEffect(() => this.actions$.pipe(
    ofType(actionsList.callStudentsRecordsApi),
    exhaustMap(() => this.studentsRecordsService.getStudentsRecords().pipe(
      map(studentsRecords => {
        console.log('API Response:', studentsRecords);
        return { type: actionsList.callStudentsRecordsApiSuccess, payload: studentsRecords }
      }),
      catchError((error) => {
        console.error('Error fetching students records:', error);
        return of({ type: '[Students API] Students Loaded Error' });
      }),
    ))
  ));
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 05:02:27