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

NestJS模块循环依赖:拦截器注入LogsService启动报错

NestJS拦截器依赖注入问题解决方案

问题分析

  • 给拦截器加@Injectable()时,启动报错:Nest can't resolve dependencies of the LogsInterceptor (?),本质是依赖未在模块中正确注册,Nest找不到要注入的LogsService。
  • 移除@Injectable()时,应用能启动但调用服务方法报错:TypeError: Cannot read properties of undefined (reading 'logRequestService'),因为Nest不会对无装饰器的类做依赖注入,this.logService始终是undefined。

分步解决

1. 保留拦截器的@Injectable()装饰器

依赖注入的前提是类必须被@Injectable()标记,修改拦截器代码:

import { CallHandler, ExecutionContext, Injectable, NestInterceptor } from '@nestjs/common';
import { Observable, tap } from 'rxjs';
import { LogsService } from './logs-service';
import { ILogModel } from './ILogModel';

@Injectable() // 必须保留这个装饰器
export class LogsInterceptor implements NestInterceptor {
  constructor(private logService: LogsService) {}

  // 其余代码不变
}

2. 在模块中注册所有依赖

确保LogsService、LogsInterceptor和DBConnection都被添加到模块的providers数组中。

如果用独立的LogsModule:

import { Module } from '@nestjs/common';
import { LogsService } from './logs-service';
import { LogsInterceptor } from './logs-interceptor';
import { DBConnection } from '../database/database.service';

@Module({
  providers: [LogsService, LogsInterceptor, DBConnection],
  exports: [LogsInterceptor] // 其他模块要使用拦截器时需导出
})
export class LogsModule {}

如果直接在AppModule中注册:

import { Module } from '@nestjs/common';
import { LogsService } from './logs/logs-service';
import { LogsInterceptor } from './logs/logs-interceptor';
import { DBConnection } from './database/database.service';

@Module({
  providers: [LogsService, LogsInterceptor, DBConnection],
})
export class AppModule {}

3. 修复this指向问题

tap操作符的回调用普通函数会导致this指向丢失,调用this.logRequest时,方法内的this不再指向拦截器实例,进而this.logService为undefined。

把回调改成箭头函数:

return next.handle().pipe(
  tap({
    next: (response) => { // 箭头函数保留this指向
      log = {
        ip: args[0].hostname,
        username: args[0].user.nombre_completo,
        tipo: args[0].method,
        path: args[0].originalUrl,
        query: args[0].query,
        params: args[0].params,
        body: args[0].body,
        response,
        statuscode: responseStatus.statusCode,
      };
      this.logRequest(log);
      console.log('after');
      return response;
    },
    error: (error) => { // 箭头函数保留this指向
      console.log(error);
      log = {
        ip: args[0].hostname,
        username: args[0].user.nombre_completo,
        tipo: args[0].method,
        path: args[0].originalUrl,
        query: args[0].query,
        params: args[0].params,
        body: args[0].body,
        response: error,
        statuscode: error.status,
      };
      this.logRequest(log);
      console.log(log);
      console.log('entrado por error');
      return error;
    },
  }),
);

或者在构造函数中绑定this:

constructor(private logService: LogsService) {
  this.logRequest = this.logRequest.bind(this);
}

验证

  1. 确认所有依赖都在模块providers中注册
  2. 拦截器保留@Injectable()装饰器
  3. 修复this指向后重启应用,测试请求日志是否正常写入

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 18:05:34