第十一章 Nest 创建动态模块

news2024/11/15 21:41:10

在 NestJS 中,动态模块允许在运行时动态添加和删除模块。这对于创建可扩展的和灵活的应用程序非常有用。

新建一个项目:

nest new dynamic-module -p npm

1717907361646.png
创建一个crud的模块:

nest g resource test

1717907490721.png
启动项目 浏览器访问 可以发现模块生效了

pnpm run start:dev

1717907603268.png
1717907581969.png
但是这个模块目前是静态的 内容固定不变 当我们想在mport 的时候给这个模块传一些参数,动态生成模块的内容 就可以使用 Dynamic Module动态模块
修改 test.module.ts: 给 TestModule 加一个 register 的静态方法,返回模块定义的对象

import { DynamicModule, Module } from '@nestjs/common';
import { TestService } from './test.service';
import { TestController } from './test.controller';

@Module({
})
export class TestModule {
  static register(options: Record<string, any>): DynamicModule {
    return {
      module: TestModule,
      providers: [
        {
          provide: 'TEST_OPTIONS',
          useValue: options
        },
        TestService
      ],
      exports: [TestService]
    }
  }
}

接着在 app.module.ts 使用

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { TestModule } from './test/test.module';

@Module({
  imports: [TestModule.register({ test: '666' })],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule { }

最后在 test.controller.ts打印

constructor(private readonly testService: TestService,
    @Inject('TEST_OPTIONS') private configOptions: Record<string, any>) { }
@Get()
  findAll() {
    console.log(this.configOptions);

    return this.testService.findAll();
  }

1717912063418.png
启动项目

pnpm run start:dev

访问 http://localhost:3000/test 可以看到控制台打印了 config 对象信息
1717912420117.png
这样我们就可以在 import 一个模块的时候,传入参数,然后动态生成模块的内容。

nest 约定了 3 种方法名:
foregister 是用于在整个应用程序中注册全局提供者的方法。当我们在应用程序的任何地方都需要访问该提供者时,可以使用 register 来注册。
forRoot 是用于在根模块中注册模块的方法。它将模块中的提供者和导出的模块注册为全局可访问的,这意味着其他模块可以直接使用这些提供者和导出的模块。
forFeature 是用于在特定模块中注册模块的方法。它将模块中的提供者和导出的模块注册为仅在该模块中可访问的。这通常用于在模块内部使用的服务和功能。
并且这些方法都可以写 xxxAsync 版本,也就是传入 useFactory 等 option,内部注册异步 provider。

Nest 还提供了另一种方式来创建动态模块
我们在生成一个新的模块:

nest g module aaa

创建一个controller:

nest g controller aaa --no-spec

新建一个 aaa.module-definition.ts 文件:

import { ConfigurableModuleBuilder } from "@nestjs/common";

/**
 * 定义了AaaModule的配置选项接口。
 * 
 * 该接口包括了aaa和bbb两个属性,分别对应不同的配置需求。
 */
export interface AaaModuleOptions {
    aaa: string;
    bbb: number;
}

/**
 * 使用ConfigurableModuleBuilder构建AaaModule的配置类和选项令牌。
 * 
 * 通过这种方式,可以动态配置模块的选项,并提供了一个令牌用于依赖注入,以便在模块中访问这些配置选项。
 */
export const { ConfigurableModuleClass, MODULE_OPTIONS_TOKEN } =
    new ConfigurableModuleBuilder<AaaModuleOptions>().build()

这段代码是使用NestJS框架定义了一个可配置的模块AaaModule。

  • AaaModuleOptions接口定义了模块的配置选项,包括aaa属性(类型为字符串)和bbb属性(类型为数字)。
  • ConfigurableModuleBuilder是一个NestJS提供的类,用于构建可配置模块。通过调用其build()方法,可以生成一个配置类和一个选项令牌。
  • ConfigurableModuleClass是生成的配置类,可以用于动态配置模块的选项。
  • MODULE_OPTIONS_TOKEN是生成的选项令牌,可以用于依赖注入,在模块中访问配置选项。

然后我们在AaaModule 里继承它

import { Module } from '@nestjs/common';
import { AaaController } from './aaa.controller';
import { ConfigurableModuleClass } from './aaa.module-definition';

@Module({
  controllers: [AaaController]
})
export class AaaModule extends ConfigurableModuleClass {}

这样这个 CccModule 就已经有了 register 和 registerAsync 方法
app.module.ts:

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { TestModule } from './test/test.module';
import { AaaModule } from './aaa/aaa.module';

@Module({
  imports: [TestModule.register({ test: '666' }),
  AaaModule.register({
    aaa: 'aaa',
    bbb: 1
  }),
  // AaaModule.registerAsync({
  //   useFactory: () => ({
  //     aaa: 'aaa',
  //     bbb: 1
  //   })
  // })
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule { }

接着我们在 Controller 注入 aaa.controller.ts

import { Controller, Get, Inject } from '@nestjs/common';
import { AaaModuleOptions, MODULE_OPTIONS_TOKEN } from './aaa.module-definition';

@Controller('aaa')
export class AaaController {

    @Inject(MODULE_OPTIONS_TOKEN)
    private options: AaaModuleOptions;

    @Get('')
    hello() {
        return this.options;
    }
}

启动项目

pnpm run start:dev

1717914850954.png
1717914955633.png
可以看到拿到了options 对象 我们可以用来做配置
如果要用 forRoot、forFeature 可以调用 setClassMethodName 函数来设置一下

import { ConfigurableModuleBuilder } from "@nestjs/common";

/**
 * 定义了AaaModule的配置选项接口。
 * 
 * 该接口包括了aaa和bbb两个属性,分别对应不同的配置需求。
 */
export interface AaaModuleOptions {
    aaa: string;
    bbb: number;
}

/**
 * 使用ConfigurableModuleBuilder构建AaaModule的配置类和选项令牌。
 * 
 * 通过这种方式,可以动态配置模块的选项,并提供了一个令牌用于依赖注入,以便在模块中访问这些配置选项。
 */
export const { ConfigurableModuleClass, MODULE_OPTIONS_TOKEN } =
    new ConfigurableModuleBuilder<AaaModuleOptions>().setClassMethodName('forRoot').build()
import { ConfigurableModuleBuilder } from "@nestjs/common";

/**
 * 定义了AaaModule的配置选项接口。
 * 
 * 该接口包括了aaa和bbb两个属性,分别对应不同的配置需求。
 */
export interface AaaModuleOptions {
    aaa: string;
    bbb: number;
}

/**
 * 使用ConfigurableModuleBuilder构建AaaModule的配置类和选项令牌。
 * 
 * 通过这种方式,可以动态配置模块的选项,并提供了一个令牌用于依赖注入,以便在模块中访问这些配置选项。
 */
export const { ConfigurableModuleClass, MODULE_OPTIONS_TOKEN } =
    new ConfigurableModuleBuilder<AaaModuleOptions>().setClassMethodName('forFeature').build()

我们还可以设置为全局模块:
setExtras 第一个参数是给 options 扩展啥 extras 属性,第二个参数是收到 extras 属性之后如何修改模块定义

import { ConfigurableModuleBuilder } from "@nestjs/common";

/**
 * 定义了AaaModule的配置选项接口。
 * 
 * 该接口包括了aaa和bbb两个属性,分别对应不同的配置需求。
 */
export interface AaaModuleOptions {
    aaa: string;
    bbb: number;
}

/**
 * 使用ConfigurableModuleBuilder构建AaaModule的配置类和选项令牌。
 * 
 * 通过这种方式,可以动态配置模块的选项,并提供了一个令牌用于依赖注入,以便在模块中访问这些配置选项。
 */
export const { ConfigurableModuleClass, MODULE_OPTIONS_TOKEN } =
    new ConfigurableModuleBuilder<AaaModuleOptions>()
        .setClassMethodName('register')
        .setExtras({
            isGlobal: true
        }, (definition, extras) => ({
            ...definition,
            global: extras.isGlobal,
        }))
        .build()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1885192.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

哪些品牌的充电宝牌子比较好用?性价比无线磁吸充电宝推荐

经常外出的朋友&#xff0c;不管是旅行聚会&#xff0c;或是商务出差&#xff0c;一旦手机电量告急&#xff0c;总会令人心生焦虑。共享充电宝不仅充电速度迟缓&#xff0c;而且价格高昂&#xff0c;有线充电宝又显得沉重&#xff0c;线缆还杂乱无章。现在随着科技的发展&#…

将exe文件添加到注册表中,实现开机时自动运行

目录 一、前言 二、代码 三、使用步骤 1.编译生成exe文件、 2.以管理员身份运行代码 3.打开注册表&#xff0c;验证结果 一、前言 在Windows操作系统中&#xff0c;将exe文件的路径添加到注册表下&#xff0c;主要用于实现程序的开机自动运行功能。 注册表路径为&#xf…

6.The hardest part about learing hard things(学一件难的事,难在哪里)

I’ve been recording a lot of podcast interviews for my upcoming book, Ultralearning.One of the reurring themes I’ve noticed in our conversations is that how people feel about learning is the overwhelming cause of the results they experience. 我为我的新书…

2024年6月总结及随笔之打卡网红点

1. 回头看 日更坚持了547天。 读《人工智能时代与人类未来》更新完成读《AI未来进行式》开更并更新完成读《AI新生&#xff1a;破解人机共存密码》开更并持续更新 2023年至2024年6月底累计码字1267912字&#xff0c;累计日均码字2317字。 2024年6月码字90659字&#xff0c;…

Git学习(常用的一些命令)

&#x1f34e;个人博客&#xff1a;个人主页 &#x1f3c6;个人专栏&#xff1a;日常聊聊 ⛳️ 功不唐捐&#xff0c;玉汝于成 目录 前言 正文 配置相关&#xff1a; 创建与克隆仓库&#xff1a; 基本操作&#xff1a; 分支操作&#xff1a; 远程仓库操作&#xff1a…

mac 安装nvm的教程

在macOS上切换Node.js版本&#xff0c;可以使用nvm&#xff08;Node Version Manager&#xff09;。以下是安装nvm和切换Node.js版本的步骤&#xff1a; 安装nvm 下载方式 终端复制输入&#xff1a; curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.…

第一后裔掉宝奖励有什么 怎么领取第一后裔掉宝奖励

第一后裔在今天就要正式上线了&#xff0c;虽然是一款刚刚上线的新游戏&#xff0c;但是其实很早就测试过了&#xff0c;而且测试过很多次&#xff0c;所以有很多已经体验过的小伙伴&#xff0c;这款游戏的玩法还是比较有意思的&#xff0c;第三人称刷宝射击加上MMORPG的玩法&a…

深入分析差分驱动器,4种情形帮您看透~

差分驱动器可以由单端或差分信号驱动&#xff0c;今天我们就利用无端接或端接信号源来分析这两种情况。 01 差分输入、无端接信号源 图1显示一个差分驱动器由一个平衡的无端接信号源驱动。这种情况通常是针对低阻抗信号源&#xff0c;信号源与驱动器之间的连接距离非常短。 图…

充电宝买哪个牌子好?2024年十大口碑最好充电宝推荐

在如今快节奏的生活中&#xff0c;充电宝已然成为我们出行必备的物品之一。然而&#xff0c;面对市场上琳琅满目的充电宝品牌和型号&#xff0c;我们常常陷入选择的困境&#xff1a;充电宝买哪个牌子好&#xff1f;2024 年&#xff0c;充电宝技术不断革新&#xff0c;新品牌层出…

重生之算法刷题之路之链表初探(三)

算法刷题之路之链表初探&#xff08;三&#xff09; 今天来学习的算法题是leecode2链表相加&#xff0c;是一道简单的入门题&#xff0c;但是原子在做的时候其实是有些抓耳挠腮&#xff0c;看了官解之后才恍然大悟&#xff01; 条件 项目解释 有题目可以知道&#xff0c;我们需…

论文题目:SpringBoot种草好物app13151

摘要 随着电子商务的快速发展和智能手机的普及&#xff0c;越来越多的用户选择通过移动应用程序进行商品浏览、购买和分享体验。种草好物App作为一个专注于商品推荐和购物体验的平台&#xff0c;具有广泛的应用前景和商业价值。本研究旨在构建一个功能丰富、性能稳定的种草好物…

第一后裔快速领取掉宝奖励礼包教程

7月2日第一后裔在steam正式上线&#xff0c;全新刷宝射击mmo玩法&#xff0c;角色的招式非常新颖 &#xff0c;画面冲击感十足&#xff0c;而且游戏人物的自定义功能非常丰富&#xff0c;超级细节真实的人物建模&#xff0c;加上超带感的服装自定义系统&#xff0c;让你能玩一整…

AI太火,今年更缺人了 (含实习)

AI太火了&#xff01;眼睛一睁一闭&#xff0c;一大堆新鲜出炉的前沿科技进展已经塞满未读列表。 许多公司更是开出了高薪&#xff0c; 读者福利&#xff1a;如果大家对大模型感兴趣&#xff0c;这套大模型学习资料一定对你有用 对于0基础小白入门&#xff1a; 如果你是零基础…

leetcode-21-回溯-全排列及其去重

一、[46]全排列 给定一个 没有重复 数字的序列&#xff0c;返回其所有可能的全排列。 示例: 输入: [1,2,3]输出: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1] ] 其中&#xff0c;不需要使用startIndex used数组&#xff0c;其实就是记录此时path里都有哪些元素…

TypeScript中,如何利用数组生成一个联合类型

本文由 ChatMoney团队出品 在开发中我们常常会遇到这样一个问题&#xff0c;代码如下&#xff1a; const arr ["a","b","c","d","e","f","g","h","i","j","k&quo…

C语言使用先序遍历创建二叉树

#include<stdio.h> #include<stdlib.h>typedef struct node {int data;struct node * left;struct node * right; } Node;Node * createNode(int val); Node * createTree(); void freeTree(Node * node);void preOrder(Node * node);// 先序创建二叉树 int main()…

在CentOS7云服务器下搭建MySQL网络服务详细教程

目录 0.说明 1.卸载不要的环境 1.1查看当前环境存在的服务mysql或者mariadb 1.2卸载不要的环境 1.2.1先关闭相关的服务 1.2.2查询曾经下载的安装包 1.2.3卸载安装包 1.2.4检查是否卸载干净 2.配置MySQLyum源 2.1获取mysql关外yum源 2.2 查看当前系统结合系统配置yum…

物联网数据可视化利器:云组态设计器全新升级

数据可视化已成为数据展示与分析领域非常重要的工具。由多种图表、3D图形组成的大屏能够帮助用户非常直观简洁地了解数据。在物联网环境下,用户在制作数据展示大屏时,对数据可视化工具提出了更高的要求,例如能够展示3D组件、灵活的图层结构、支持多种数据源、实时的数据更新、图…

[教程]Gitee保姆级图文使用教程

我们在日常的工作过程中经常会遇到&#xff0c;家里和公司资料文件同步的问题&#xff0c;以及项目开发过程中的协作问题。Git就完美的解决了这些问题&#xff0c;但是由于 Git国外服务器的原因平时网络太慢了&#xff0c;不过还好有国内的托管平台Gitee&#xff08;码云&#…

Ubuntu20.04 有线网络图标消失解决方案

Ubuntu20.04 有线网络图标消失解决方案 问题描述&#xff1a; ubuntu20.04系统提示的software updater有软件包更新&#xff0c;按提示安装更新软件包&#xff0c;重启系统后&#xff0c;ubuntu系统的网络图标消失不见&#xff1b;无法正常上网&#xff1b;检查网口&#xff0…