Nest.js全局注册Mongoose事务拦截器依赖注入报错问题
Got it, let's break down why you're hitting this error and how to fix it. The core issue here is that when you manually instantiate your interceptor with new MyInterceptor(), NestJS's dependency injection (DI) container doesn't get a chance to inject the Connection you're requesting via @InjectConnection(). Let's walk through two reliable solutions:
Solution 1: Register the Interceptor via a Module with the APP_INTERCEPTOR Token
This is the recommended approach for global interceptors that rely on DI. You can register your interceptor in any module (usually your root AppModule) using the APP_INTERCEPTOR provider token, which tells Nest to apply this interceptor across your entire application.
First, let's confirm your interceptor setup (this is what your code might look like):
import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common'; import { InjectConnection } from '@nestjs/mongoose'; import { Connection } from 'mongoose'; import { Observable } from 'rxjs'; @Injectable() export class MyInterceptor implements NestInterceptor { constructor(@InjectConnection() private readonly connection: Connection) {} async intercept(context: ExecutionContext, next: CallHandler): Promise<Observable<any>> { // Your transaction logic using the injected connection const session = await this.connection.startSession(); session.startTransaction(); try { const result = await next.handle().toPromise(); await session.commitTransaction(); return Promise.resolve(result); } catch (error) { await session.abortTransaction(); throw error; } finally { session.endSession(); } } }
Now update your AppModule to register the interceptor globally:
import { Module } from '@nestjs/common'; import { APP_INTERCEPTOR } from '@nestjs/core'; import { MongooseModule } from '@nestjs/mongoose'; import { MyInterceptor } from './my.interceptor'; @Module({ imports: [ MongooseModule.forRoot('mongodb://localhost:27017/your-database-name'), // Add other modules here ], providers: [ { provide: APP_INTERCEPTOR, useClass: MyInterceptor, }, ], }) export class AppModule {}
With this setup, Nest's DI container will automatically inject the Connection into MyInterceptor when it creates the instance—no manual parameter passing needed.
Solution 2: Fetch the Interceptor from the DI Container for app.useGlobalInterceptors
If you prefer using app.useGlobalInterceptors (maybe for dynamic registration logic), you need to retrieve the interceptor instance from Nest's DI container instead of creating it with new.
First, register MyInterceptor as a provider in your AppModule:
// Inside AppModule providers: [MyInterceptor],
Then in your main.ts, use app.get() to get the fully instantiated interceptor (with dependencies injected):
import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; import { MyInterceptor } from './my.interceptor'; async function bootstrap() { const app = await NestFactory.create(AppModule); // Get the interceptor instance from the DI container const myInterceptor = app.get(MyInterceptor); app.useGlobalInterceptors(myInterceptor); await app.listen(3000); } bootstrap();
This works because app.get() asks the DI container to create or retrieve the MyInterceptor instance, which includes injecting the required Connection automatically.
Why Your Original Approach Failed
When you use new MyInterceptor(), you're bypassing Nest's DI system entirely. The interceptor's constructor expects a Connection parameter, but you're not passing it—hence the error asking for the connection dependency. Nest can only inject dependencies when it's the one responsible for creating the class instance.
内容的提问来源于stack exchange,提问作者ks9

