聊聊Nest 全局模块和生命周期

0 阅读2分钟

全局模块 @Global

先生成两个模块

nest g resource aaa --no-spec 
nest g resource bbb --no-spec

AaaModule 添加 exports 的 provider:

image.png

BbbModule 里 imports:

image.png

这样就可以在 BbbModule 内注入 AaaService:

image.png

npm run start:dev

image.png

image.png

常常这样引入

但如果 一个模块被多个地方 引用如何写更好?

在 AaaModule 上加一个 @Global 的装饰器,然后在 BbbModule 里把 AaaModule 的 imports 去掉

image.png

image.png

此时这个使用或叫注入也没问题

image.png

不过全局模块还是尽量少用,不然注入的很多 provider 都不知道来源,会降低代码的可维护性,类似于 js 当中你不会写很多的 全局变量 然后多个文件使用,会引发更大的混乱

生命周期

Nest 在启动的时候,会递归解析 Module 依赖,扫描其中的 provider、controller,注入它的依赖。

全部解析完后,会监听网络端口,开始处理请求。

这个过程中,Nest 暴露了一些生命周期方法:

image.png

首先,递归初始化模块,会依次调用模块内的 controller、provider 的 onModuleInit 方法,然后再调用 module 的 onModuleInit 方法。

全部初始化完之后,再依次调用模块内的 controller、provider 的 onApplicationBootstrap 方法,然后调用 module 的 onApplicationBootstrap 方法

然后监听网络端口。

之后 Nest 应用就正常运行了。

这个过程中,onModuleInit、onApplicationBootstrap 都是我们可以实现的生命周期方法

尝试看看 创建两个新的模块

nest g resource ccc --no-spec
nest g resource ddd --no-spec

controller 写

image.png

service 写

image.png

module 写

image.png

重启一下

可以看到打印的结果

image.png

应用销毁的时候也同样有生命周期

image.png

添加销毁周期 看下

image.png

image.png

image.png

所有的生命周期函数都是支持 async 的

比如

@Injectable()
export class UserService implements OnModuleInit {
  async onModuleInit() {
    await this.syncCache()
  }
}

常用 moduleRef 就是当前模块的引用

image.png

onApplicationShutdown 的生命周期里,拿到当前模块的引用 moduleRef,调用 get 方法,传入 token,取出对应的 provider 实例,然后调用它的方法

image.png