Nestjs 搞明白全局注册的两种方式的区别
区分两种注册方式
在nestjs中我们有两种注册全局的方式,一种是通过NestFactory.create
得到app实例,在通过app.useGlobalXXX
的方式去注册全局的东西,比如全局拦截器,全局过滤器等。
import { NestFactory } from "@nestjs/core";
import { AppModule } from "./app.module";
import { ResultFormatInterceptor } from "@/utils/interceptor";
async function bootstrap() {
const app = await NestFactory.create(AppModule);
// 全局拦截器
app.useGlobalInterceptors(new ResultFormatInterceptor());
await app.listen(3000);
}
bootstrap();
第二种是在app.module.ts
中,通过app模块的providers
属性,进行注册,此时我们需要从nestjs中引入预设的全局常量名APP_XXXX
,然后再进行注册。
import { Module } from "@nestjs/common";
import { JwtAuthGuard } from "./utils/guards";
import { APP_GUARD} from "@nestjs/core";
@Module({
imports: [],
controllers: [],
providers: [
{
provide: APP_GUARD,
useClass: JwtAuthGuard
},
]
})
export class AppModule {}
那么我们如何选择合适的注册方式,还是很重要的。
在之前的文章中我们讲解了Nestjs的依赖注入,其中有这种用法:
import { ExecutionContext, Injectable, UnauthorizedException, NotFoundException } from "@nestjs/common";
import { AuthGuard } from "@nestjs/passport";
import { IS_PUBLIC_KEY } from "src/utils/decorators";
import { Reflector } from "@nestjs/core";
@Injectable()
export class JwtAuthGuard extends AuthGuard("jwt") {
constructor(private reflector: Reflector) {
super();
}
/** 验证token */
canActivate(context: ExecutionContext): boolean | Promise<boolean> | Observable<boolean> {
// 是否是公共路由
const isPublic = this.reflector.getAllAndOverride<boolean>(IS_PUBLIC_KEY, [
context.getHandler(),
context.getClass()
]);
if (isPublic) return true;
// 校验token
return super.canActivate(context);
}
}
在这个全局守卫中,我们通过private reflector: Reflector
注入了reflector
依赖,这就意味着我们在new这个守卫的时候,是必须传入reflector
参数,如果通过app.useGlobalGuards()
的方式,手动实例化,我们是没办法获取到这个参数依赖的。
准确的来说也不是没办法,只是不方便。
所以我们通过在app.module.ts
的providers
注册为全局,此时实例化的操作交给了Nestjs去做,它就可以识别到所需要的依赖,从而正确传入参数。
所以,从这点去区分,我们就可以很好的判别,该用何种方式来实现全局注册了。
只要这个类它使用了依赖注入的方式载入依赖,那么我们就通过providers
的方式注入,将实例化的操作交给Nestjs去处理。
反之,它没有使用依赖注入,那么就可以直接app.useGlobalXXX
的方式实现注册。
硬要用useGlobalXXX的方式注册
这种方式也不是不行,第一是便于阅读,但是写法上会繁琐一些。
首先我们需要再app.module.ts
中通过默认方式加载对应的依赖。
import { Module } from "@nestjs/common";
import { JwtAuthGuard } from "./utils/guards";
@Module({
imports: [],
controllers: [],
providers: [
JwtAuthGuard
]
})
export class AppModule {}
由于没有使用APP_GUARD
常量的方式注册,所以它现在只是一个普通依赖。
再去main.ts中注册:
import { NestFactory } from "@nestjs/core";
import { AppModule } from "./app.module";
import { JwtAuthGuard } from "./utils/guards";
async function bootstrap() {
const app = await NestFactory.create(AppModule);
const jwtAuthGuard = app.get(JwtAuthGuard);
app.useGlobalGuards(jwtAuthGuard);
await app.listen(3000);
}
bootstrap();
我们通过get
的方式取出jwtAuthGuard
实例,此时它的实例化也是通过Nestjs实现的,所以它的依赖也是成功注入了的,我们再将他注册到全局即可。
当然这种方式有可能会碰到其它情况而导致不适用,但是目前本人还没有碰到这种情况,等以后遇到了再看看解决方案。
本文系作者 @木灵鱼儿 原创发布在木灵鱼儿站点。未经许可,禁止转载。
全部评论 2
2
Google Chrome MacOS木灵鱼儿
FireFox Windows 10