神光《Nest 通关秘籍》学习总结-全局模块和生命周期详解
最近在学习神光大神的《Nest通关秘籍》,该小册主要包含下面这些内容:
想购买的可以点击《传送门》。
接下来的日子里,我将更新一系列的学习笔记。感兴趣的可以关注我的专栏《Nest 通关秘籍》学习总结。
特别申明:本系列文章已经经过作者本人的允许。 大家也不要想着白嫖,我的笔记只是个人边学习边记录的,不是很完整,大家想要深入学习还是要自己去购买原版小册。
本章我们来学习nest中的全局模块和生命周期。
全局模块
搞一个 nest 项目:
nest new global-and-lifecycle -p pnpm
首先,想在一个模块中引入另一个模块需要怎么做呢?
创建两个 CURD 的模块:
nest g resource aaa --no-spec
nest g resource bbb --no-spec
在 AaaModule 里指定 exports 的 provider:
import { Module } from '@nestjs/common';
import { AaaService } from './aaa.service';
import { AaaController } from './aaa.controller';
@Module({
controllers: [AaaController],
providers: [AaaService],
exports: [AaaService],
})
export class AaaModule {}
然后在 BbbModule 里 imports:
import { Module } from '@nestjs/common';
import { BbbService } from './bbb.service';
import { BbbController } from './bbb.controller';
import { AaaModule } from 'src/aaa/aaa.module';
@Module({
imports: [AaaModule],
controllers: [BbbController],
providers: [BbbService],
})
export class BbbModule {}
这样就可以在 BbbModule 内注入 AaaService 了:
import { Controller, Get, Post, Body, Patch, Param, Delete } from '@nestjs/common';
import { BbbService } from './bbb.service';
import { AaaService } from '../aaa/aaa.service';
@Controller('bbb')
export class BbbController {
constructor(
private readonly bbbService: BbbService,
private readonly aaaService: AaaService,
) {}
@Get()
findAll() {
return 'this action is bbb ' + this.aaaService.findAll();
}
}
这是我们常用的引入 Module 的方式。
但如果这个 AaaModule 被很多地方引用呢?
每个模块都需要 imports 太麻烦了,这时候就可以使用Global
把它声明为全局的:
import { Module, Global } from '@nestjs/common';
import { AaaService } from './aaa.service';
import { AaaController } from './aaa.controller';
@Global() // 声明为全局
@Module({
controllers: [AaaController],
providers: [AaaService],
exports: [AaaService],
})
export class AaaModule {}
然后在B模块中把imports
去掉:
import { Module } from '@nestjs/common';
import { BbbService } from './bbb.service';
import { BbbController } from './bbb.controller';
@Module({
imports: [],
controllers: [BbbController],
providers: [BbbService],
})
export class BbbModule {}
这样依然可以在B模块中引入A模块了。
像上面这样使用Global
声明得就是全局模块。
现在我们来看看个个模块之间引用的流程图:
我大概画了这么一张图:
- 首先在
App.module
中引入Aaa.module
和Bbb.module
。这样才能把这两个模块注入IOC容器中。 - 在
Aaa.module
中exports了一个Aaa.service
,就是是把它的Provider暴露出来了,这里的Provider我们指的是Aaa.service
中的方法。 - 然后在
Bbb.module
中imports了一下Aaa.module
,也就是把Aaa.service
中方法引入进来了。 - 最后我们就可以在
Bbb.controller
中使用Aaa.service
的方法了。
生命周期
应用初始化的时候生命周期:
在整个初始化生命周期中,nest是这样执行的:首先,Nest在初始化的会先递归Module依赖模块,会依次调用模块内的 controller、provider 的 onModuleInit
方法,然后再调用 module 的 onModuleInit
方法。
全部初始化完之后,再依次调用模块内的 controller、provider 的 onApplicationBootstrap
方法,然后调用 module 的 onApplicationBootstrap
方法然后监听网络端口。之后 Nest 应用就正常运行了。
应用销毁的时候生命周期:
在整个销毁的声明周期中,先调用每个模块的 controller、provider 的 onModuleDestroy
方法,然后调用 Module 的 onModuleDestroy
方法。
之后再调用每个模块的 controller、provider 的 beforeApplicationShutdown
方法,然后调用 Module 的 beforeApplicationShutdown
方法。然后停止监听网络端口。之后调用每个模块的 controller、provider 的 onApplicationShutdown
方法,然后调用 Module 的 onApplicationShutdown
方法。之后停止进程。
下面我们在代码中实际看看。
首先我们新建一个ccc
模块:
nest g resource ccc --no-spec
然后在对应的controller、service、module
里分别添加下面几个生命周期函数:
OnModuleInit
OnApplicationBootstrap
OnModuleDestroy
BeforeApplicationShutdown
OnApplicationShutdown
ccc.module.ts文件:
import {
Module,
OnModuleInit,
OnApplicationBootstrap,
OnModuleDestroy,
BeforeApplicationShutdown,
OnApplicationShutdown,
} from '@nestjs/common';
import { CccService } from './ccc.service';
import { CccController } from './ccc.controller';
@Module({
controllers: [CccController],
providers: [CccService],
})
export class CccModule
implements
OnModuleInit,
OnApplicationBootstrap,
OnModuleDestroy,
BeforeApplicationShutdown,
OnApplicationShutdown
{
onModuleInit() {
console.log('CccModule OnModuleInit');
}
onApplicationBootstrap() {
console.log('CccModule OnApplicationBootstrap');
}
onModuleDestroy() {
console.log('CccModule onModuleDestroy');
}
beforeApplicationShutdown() {
console.log('CccModule beforeApplicationShutdown');
}
onApplicationShutdown() {
console.log('CccModule onApplicationShutdown');
}
}
ccc.controller.ts文件:
import {
Controller,
OnModuleInit,
OnApplicationBootstrap,
OnModuleDestroy,
BeforeApplicationShutdown,
OnApplicationShutdown,
} from '@nestjs/common';
import { CccService } from './ccc.service';
@Controller('ccc')
export class CccController
implements
OnModuleInit,
OnApplicationBootstrap,
OnModuleDestroy,
BeforeApplicationShutdown,
OnApplicationShutdown
{
constructor(private readonly cccService: CccService) {}
onModuleInit() {
console.log('CccController OnModuleInit');
}
onApplicationBootstrap() {
console.log('CccController OnApplicationBootstrap');
}
onModuleDestroy() {
console.log('CccController onModuleDestroy');
}
beforeApplicationShutdown() {
console.log('CccController beforeApplicationShutdown');
}
onApplicationShutdown() {
console.log('CccController onApplicationShutdown');
}
}
ccc.service.ts文件:
import {
Injectable,
OnModuleInit,
OnApplicationBootstrap,
OnModuleDestroy,
BeforeApplicationShutdown,
OnApplicationShutdown,
} from '@nestjs/common';
@Injectable()
export class CccService
implements
OnModuleInit,
OnApplicationBootstrap,
OnModuleDestroy,
BeforeApplicationShutdown,
OnApplicationShutdown
{
onModuleInit() {
console.log('CccService OnModuleInit');
}
onApplicationBootstrap() {
console.log('CccService OnApplicationBootstrap');
}
onModuleDestroy() {
console.log('CccService onModuleDestroy');
}
beforeApplicationShutdown() {
console.log('CccService beforeApplicationShutdown');
}
onApplicationShutdown() {
console.log('CccService onApplicationShutdown');
}
}
首先我们来看看初始化的时候,声明周期执行的顺序:
从打印的日志可以看出来执行顺序大概如下:
- controller的
onModuleInit
执行 - service的
onModuleInit
执行 - module的
onModuleInit
执行 - controller的
onApplicationBootstrap
执行 - service的
onApplicationBootstrap
执行 - module的
onApplicationBootstrap
执行
接下来我们在main.ts中添加一个定时器,调用app.close()
来触发销毁的生命周期:
// main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
await app.listen(3000);
setTimeout(() => {
// app.close();
}, 3000);
}
bootstrap();
可以看到,它的执行顺序是这样的:
- controller的
onModuleDestroy
执行 - service的
onModuleDestroy
执行 - module的
onModuleDestroy
执行 - controller的
beforeApplicationShutdown
执行 - service的
beforeApplicationShutdown
执行 - module的
beforeApplicationShutdown
执行 - controller的
onApplicationShutdown
执行 - service的
onApplicationShutdown
执行 - module的
onApplicationShutdown
执行
以上就是Nest所有的生命周期函数,一共有五个。
转载自:https://juejin.cn/post/7242163788039634999