nestjs 全栈进阶--module

2024-04-07 13:28
文章标签 进阶 module 全栈 nestjs

本文主要是介绍nestjs 全栈进阶--module,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

视频教程

10_模块@Module1_哔哩哔哩_bilibili

1. 模块@Module

在 Nest.js 中,Module 是框架的核心概念之一,用于组织和管理应用程序的不同部分,包括服务、控制器、中间件以及其他模块的导入。每个 Nest.js 应用程序至少有一个根模块(通常命名为 AppModule),并且可以根据需要创建更多的模块以实现更好的代码组织和模块化。

模块的主要功能和用途包括:

  1. 服务注册
    • 使用 providers 属性来注册服务,这些服务可以被其他模块通过依赖注入(DI)系统来获取和使用。
  1. 控制器注册
    • 使用 controllers 属性来注册控制器,它们处理 HTTP 请求并返回响应。
  1. 模块导入
    • 使用 imports 属性来导入其他模块,这样就可以在整个应用范围内共享和使用已导入模块的控制器和服务。
  1. 导出提供者
    • 使用 exports 属性来导出模块内的服务和其他提供者,使其可供其他导入该模块的模块使用。
  1. 全局中间件
    • 使用 middleware 属性注册全局中间件,这些中间件会对所有的 HTTP 请求生效。
  1. 路由前缀
    • 通过 path 属性为模块内的所有控制器添加路由前缀,方便进行路由分组和管理。
  1. 配置绑定
    • 可以在模块级别绑定配置对象,这些配置可在模块内的服务中通过 @Inject() 注解注入和使用。
  1. 动态模块
    • 通过 register() 或forRoot() 或 forFeature() 方法,可以创建动态模块,根据需要动态加载和配置模块。
nest new module -p pnpm
pnpm start:dev

2. 基本用法

nest g res aaa

当我们使用nest g res aaa 创建一个CURD 模板的时候 nestjs 会自动帮我们引入模块

在aaa.module中也自动处理了AaaController, AaaService

3. 共享模块

nest g resource bbb --no-spec // --no-spec 是不生成测试文件

在 AaaModule 里指定 exports 的 provider:

然后在 BbbModule 里 imports:

这样就可以在bbb中使用aaa的service了

pnpm run start:dev
http://localhost:3000/bbb

4. 全局模块

如果这个 AaaModule 被很多地方引用,每个模块都 imports 太麻烦了,这时候就可以把它声明为全局的

@Global()

我们给 aaa 模块添加 @Global() 他便注册为全局模块

在bbb 模块使用无须在module import 导入

依然是可以注入的:

注:全局模块尽量少用,注入的很多 provider 不知道来源,降低代码的可维护性。

5. 动态模块

我们上面讲的模块都是静态的,也就是它的内容是固定不变的,每次 import 都是一样,有的时候我们希望 import 的时候给这个模块传一些参数,动态生成模块的内容,这时就需要用到动态模块了。

动态模块主要就是为了给模块传递参数 可以给该模块添加一个静态方法 用来接受参数

nest g resource ccc --no-spec // --no-spec 是不生成测试文件

他自动生成的模块是这样的

我们现在来改成Dynamic Module

我们给 CccModule 加一个 register 的静态方法,返回模块定义的对象。和在装饰器里定义的时候的区别,只是多了一个 module 属性。

现在我们在去app.module中重新处理下他的import

import 的时候就得这样用了,通过 register 方法传入参数,返回值就是模块定义,现在我们在运行项目,访问http://localhost:3000/ccc

可以看到依然是正常的

而且这时候我们把传入的 options 通过 useValue 创建的 provider,这样模块内部就可以注入它了。

再次在浏览器访问

这样我们就可以在 import 一个模块的时候,传入参数,然后动态生成模块的内容,这就是 Dynamic Module。

register 这个方法其实叫啥都行,但 nest 约定了 3 种方法名:

  • register:用一次模块传一次配置,比如这次调用是 CccModule.register({name: 'xt'}),下一次就是 CccModule.register({name: 'lxc'}) 了
  • forRoot:配置一次模块用多次,比如 XxxModule.forRoot({}) 一次,之后就一直用这个 Module,一般在 AppModule 里 import
  • forFeature:用了 forRoot 固定了整体模块,用于局部的时候,可能需要再传一些配置,比如用 forRoot 指定了数据库链接信息,再用 forFeature 指定某个模块访问哪个数据库和表。

其实 forRoot、forFeature、register 本质上没区别,只是我们约定了它们使用上的一些区别。

6. Nest 提供创建动态模块的方式

nest g module ddd
nest g controller ddd --no-spec

这次我们不手动写 register、registerAsync 等方法了,用 builder 来生成。

import { ConfigurableModuleBuilder } from "@nestjs/common";export interface DddModuleOptions {name: string;age: number;
}export const { ConfigurableModuleClass, MODULE_OPTIONS_TOKEN } =new ConfigurableModuleBuilder<DddModuleOptions>().build();

用 ConfigurableModuleBuilder 生成一个 class,这个 class 里就带了 register、registerAsync 方法。

返回的 ConfigurableModuleClass、MODULE_OPTIONS_TOKEN 分别是生成的 class 、options 对象的 token。

然后 DddModule 继承它,这样这个 DddModule 就已经有了 register 和 registerAsync 方法了

那现在如何在 Module 内注入这个 options 呢?记得 build class 的时候返回了一个 token 么?

就用这个注入:

当然,options 对象不是这么用的,一般是用来做配置,内部的 provider 基于它来做一些设置,这里只是演示。

你还可以用 registerAsync 方法,用 useFactory 动态创建 options 对象:

前面我们说还可以用 forRoot、forFeature 这样的方法,那用 builder 的方式如何生成这样的 class 呢?调用 setClassMethodName 设置下就好了

如果你还想根据传入的参数决定是否设置为全局模块,那就要这样写

import { ConfigurableModuleBuilder } from "@nestjs/common";export interface DddModuleOptions {name: string;age: number;
}export const { ConfigurableModuleClass, MODULE_OPTIONS_TOKEN } =new ConfigurableModuleBuilder<DddModuleOptions>().setClassMethodName('register').setExtras({isGlobal: true,}, (definition, extras) => ({...definition,global: extras.isGlobal,})).build();

setExtras 第一个参数是给 options 扩展啥 extras 属性,第二个参数是收到 extras 属性之后如何修改模块定义。我们定义了 isGlobal 的 option,收到它之后给模块定义加上个 global。

然后我们会发现一个问题, 在我们使用的时候他没有isGlobal 属性

因为我们用的是这个类型:

我们应该用builder 返回的类型

这个 ASYNC_OPTIONS_TYPE 是 async 方式创建模块的 otpion 类型.

在实际项目中 你可以自己创建动态模块,也可以使用nest提供的 ConfigurableModuleBuilder,它只是对我们定义 register、registerAsync 的过程做了封装。

这篇关于nestjs 全栈进阶--module的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/882722

相关文章

如何解决idea的Module:‘:app‘platform‘android-32‘not found.问题

《如何解决idea的Module:‘:app‘platform‘android-32‘notfound.问题》:本文主要介绍如何解决idea的Module:‘:app‘platform‘andr... 目录idea的Module:‘:app‘pwww.chinasem.cnlatform‘android-32

Spring Boot + MyBatis Plus 高效开发实战从入门到进阶优化(推荐)

《SpringBoot+MyBatisPlus高效开发实战从入门到进阶优化(推荐)》本文将详细介绍SpringBoot+MyBatisPlus的完整开发流程,并深入剖析分页查询、批量操作、动... 目录Spring Boot + MyBATis Plus 高效开发实战:从入门到进阶优化1. MyBatis

Python中ModuleNotFoundError: No module named ‘timm’的错误解决

《Python中ModuleNotFoundError:Nomodulenamed‘timm’的错误解决》本文主要介绍了Python中ModuleNotFoundError:Nomodulen... 目录一、引言二、错误原因分析三、解决办法1.安装timm模块2. 检查python环境3. 解决安装路径问题

Java进阶学习之如何开启远程调式

《Java进阶学习之如何开启远程调式》Java开发中的远程调试是一项至关重要的技能,特别是在处理生产环境的问题或者协作开发时,:本文主要介绍Java进阶学习之如何开启远程调式的相关资料,需要的朋友... 目录概述Java远程调试的开启与底层原理开启Java远程调试底层原理JVM参数总结&nbsMbKKXJx

MySQL进阶之路索引失效的11种情况详析

《MySQL进阶之路索引失效的11种情况详析》:本文主要介绍MySQL查询优化中的11种常见情况,包括索引的使用和优化策略,通过这些策略,开发者可以显著提升查询性能,需要的朋友可以参考下... 目录前言图示1. 使用不等式操作符(!=, <, >)2. 使用 OR 连接多个条件3. 对索引字段进行计算操作4

JavaScript中的reduce方法执行过程、使用场景及进阶用法

《JavaScript中的reduce方法执行过程、使用场景及进阶用法》:本文主要介绍JavaScript中的reduce方法执行过程、使用场景及进阶用法的相关资料,reduce是JavaScri... 目录1. 什么是reduce2. reduce语法2.1 语法2.2 参数说明3. reduce执行过程

nginx-rtmp-module模块实现视频点播的示例代码

《nginx-rtmp-module模块实现视频点播的示例代码》本文主要介绍了nginx-rtmp-module模块实现视频点播,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习... 目录预置条件Nginx点播基本配置点播远程文件指定多个播放位置参考预置条件配置点播服务器 192.

nginx-rtmp-module构建流媒体直播服务器实战指南

《nginx-rtmp-module构建流媒体直播服务器实战指南》本文主要介绍了nginx-rtmp-module构建流媒体直播服务器实战指南,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有... 目录1. RTMP协议介绍与应用RTMP协议的原理RTMP协议的应用RTMP与现代流媒体技术的关系2

Python进阶之Excel基本操作介绍

《Python进阶之Excel基本操作介绍》在现实中,很多工作都需要与数据打交道,Excel作为常用的数据处理工具,一直备受人们的青睐,本文主要为大家介绍了一些Python中Excel的基本操作,希望... 目录概述写入使用 xlwt使用 XlsxWriter读取修改概述在现实中,很多工作都需要与数据打交

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin