【Nestjs学习日记】Module

作者:markzzw 时间:2024-1-29

线上代码:CodeSandbox

Github:zhangzewei/nest-learning-tutorial
系列阅读

  1. 【Nestjs学习日记】初识nestjs
  2. 【Nestjs学习日记】Nest Controller
  3. 【Nestjs学习日记】抛出异常
  4. 【Nestjs学习日记】Module

在NestJS中,模块(Module)是组织和管理应用程序的基本构建块之一。模块提供了一种将相关功能组织在一起的方式,使代码更具可维护性和可扩展性。在这个【NestJS学习日记】系列的本篇中,我们将深入探讨NestJS中的模块概念。

模块在NestJS中扮演着重要的角色。每个NestJS应用程序都由一个或多个模块组成,每个模块都代表着一个特定的功能区域。模块可以包含控制器、服务、提供者和其他相关的组件,它们一起协同工作以实现特定的功能。

在这个【NestJS学习日记】系列的本篇中,我们将学习如何创建和使用模块。我们将学习如何定义模块、如何将模块导入到其他模块中以及如何使用模块中定义的组件。我们还将研究模块之间的依赖关系和模块的层次结构。

通过学习NestJS中的模块概念,我们将能够更好地组织和管理我们的应用程序代码,使其更具可维护性和可扩展性。模块是构建NestJS应用程序的基础,深入理解和掌握模块的概念将有助于我们更好地开发出高质量的应用程序。

在接下来的文章中,我们将深入研究NestJS中的模块概念,包括如何创建和使用模块、模块之间的关系和层次结构等。让我们一起开始这个令人兴奋的学习之旅,掌握NestJS中模块的技能!

创建 Module

使用 @nestjs/cli 进行 Module 的创建,如果没有安装可以运行 npm install @nestjs/cli -g ;首先我们可以使用 nest generate --help,查看能够运行的命令有哪些。

shell 复制代码
┌───────────────┬─────────────┬──────────────────────────────────────────────┐
│ name          │ alias       │ description                                  │
│ application   │ application │ Generate a new application workspace         │
│ class         │ cl          │ Generate a new class                         │
│ configuration │ config      │ Generate a CLI configuration file            │
│ controller    │ co          │ Generate a controller declaration            │
│ decorator     │ d           │ Generate a custom decorator                  │
│ filter        │ f           │ Generate a filter declaration                │
│ gateway       │ ga          │ Generate a gateway declaration               │
│ guard         │ gu          │ Generate a guard declaration                 │
│ interceptor   │ itc         │ Generate an interceptor declaration          │
│ interface     │ itf         │ Generate an interface                        │
│ library       │ lib         │ Generate a new library within a monorepo     │
│ middleware    │ mi          │ Generate a middleware declaration            │
│ module        │ mo          │ Generate a module declaration                │
│ pipe          │ pi          │ Generate a pipe declaration                  │
│ provider      │ pr          │ Generate a provider declaration              │
│ resolver      │ r           │ Generate a GraphQL resolver declaration      │
│ resource      │ res         │ Generate a new CRUD resource                 │
│ service       │ s           │ Generate a service declaration               │
│ sub-app       │ app         │ Generate a new application within a monorepo │
└───────────────┴─────────────┴──────────────────────────────────────────────┘

在上面的命令表中,可以使用 nest generate module moduleName 创建一个 Module,那么我们创建一个 CatModule。

当运行这个命令的时候,不仅会创建一个 cat.module.ts 文件还会将这个 Module 插入到 app.module.ts 中。

Module imports

可以看到在新增一个 module 的时候,nestjs 会自动将这个 module 放入 app.module.ts 的 imports 数组中,这代表在创建 AppModule 的时候也会加载 CatModule,让我们来验证一下,新建一个 cat.controller.ts。

同样,新增一个 Controller 的时候,也会在对应的 Module 中将其插入到 controllers 的数组里,然后我们给新的这个 cat.controller.ts 增加一个 get 方法。

此时,访问 '/cat' 路由会得到对应的返回,但是当我们将 CatModule 从 app.module.ts 的 imports 里去掉之后,访问 '/cat' 就会得到 404 的结果。

Module providers

在 Module 中还有一个配置是 providers 数组,这个是将所需要的其他的服务注入到当前 Module 中,我们新建一个 cat.service.ts nest generate service cat,在里面写上一个 getCats 的方法。

cat.service.ts

ts 复制代码
import { Injectable } from '@nestjs/common';

@Injectable()
export class CatService {
  getCats() {
    return 'cats in service';
  }
}

然后在 cat.module.ts 中,将 CatService 注入。

ts 复制代码
import { Module } from '@nestjs/common';
import { CatController } from './cat.controller';
import { CatService } from './cat.service';

@Module({
  controllers: [CatController],
  providers: [CatService], // 注入cat service
})
export class CatModule {}

这样就能够在 cat.controller.ts 中使用 CatService。

ts 复制代码
import { Controller, Get } from '@nestjs/common';
import { CatService } from './cat.service';
@Controller('cat')
export class CatController {
  constructor(private catService: CatService) {} // 通过依赖注入的方式拿到拿到CatService
  @Get()
  getCats() {
    return this.catService.getCats();
  }
}

在不同的 module 中依赖注入 providers

假设在 appModule 中需要用到 cat service 中的某个方法,那么我们在 app.controller.ts 中也是用在 constructor 中依赖注入的方式调用 CatService。

ts 复制代码
import {
  Controller,
  Get,
  Param
} from '@nestjs/common';
import { CatService } from './cat/cat.service';

@Controller('app')
export class AppController {
  constructor(private readonly catService: CatService) {}

  @Get('hello/:name')
  getHello(@Param('name') a: string): string {
    return this.catService.getHello();
  }
}

然后在 app.module.ts 中将CatService注入providers。

ts 复制代码
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { CatModule } from './cat/cat.module';
import { CatService } from './cat/cat.service';

@Module({
  imports: [CatModule],
  controllers: [AppController],
  providers: [AppService, CatService],
})
export class AppModule {}

这样子也能够使用到 CatService 中的方法和数据,但是两个在 cat.controller.ts 和 app.controller.ts 中的 CatService 不同一个。我们来做个验证。

我们先给 CatService 新增两个方法和一个属性,属性作为一个数据flag参考。

ts 复制代码
import { Injectable } from '@nestjs/common';

@Injectable()
export class CatService {
  isChanged = false;
  constructor() {
    console.log('cat service created');
  }
  setIsChanged() {
    this.isChanged = true;
  }

  getIsChanged() {
    return this.isChanged;
  }
}

然后在 cat.controller.ts 新增一个 'change' 路由,去调用一下 CatService 的 setIsChanged 函数。

ts 复制代码
import { Controller, Get } from '@nestjs/common';
import { CatService } from './cat.service';
@Controller('cat')
export class CatController {
  constructor(private catService: CatService) {}
  @Get()
  getCats() {
    return 'cat controller flag: ' + this.catService.getIsChanged();
  }

  @Get('change')
  changeCats() {
    this.catService.setIsChanged();
    return 'cat controller changed, flag: ' + this.catService.getIsChanged();
  }
}

在 app.controller.ts 中调用 CatService 的 getIsChanged 函数,我们会发现:

  1. 首先运行项目的 terminal 中会打印两次 cat service created

  2. 访问 '/cat/change' 修改 isChanged 为 true 之后,再访问 'app/hello/name',发现返回的 isChanged 还是初始的 false。

这个验证说明了如果分别在 module 中 注入的provider是独立的,并不是共享的,那么怎么才能做到共享呢,就是使用 module 的 exports。

Module exports

先修改 cat.module.ts,将 CatService 放入 exports 数组中。

ts 复制代码
import { Module } from '@nestjs/common';
import { CatController } from './cat.controller';
import { CatService } from './cat.service';

@Module({
  controllers: [CatController],
  providers: [CatService],
  exports: [CatService],
})
export class CatModule {}

然后去掉 app.module.ts 中 providers 中的 CatService,这样子 app.controller.ts 使用的 CatService 就是通过 imports CatModule 进来的,此时,两个不同Controller中使用的service就是同一个了。

ts 复制代码
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { CatModule } from './cat/cat.module';

@Module({
  imports: [CatModule],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

使用相同的验证方法可以看到,两边的数据已经达到同步,并且 terminal 也只打印了一次 cat service created

总结

module 是 nestjs 的一个重要概念,他可以有很多种组合,也是使 nestjs 变得高内聚低耦合的重要特性,即通过 imports,providers和exports 对代码进行组织。

相关推荐
轻口味1 小时前
命名空间与模块化概述
开发语言·前端·javascript
前端小小王2 小时前
React Hooks
前端·javascript·react.js
迷途小码农零零发2 小时前
react中使用ResizeObserver来观察元素的size变化
前端·javascript·react.js
娃哈哈哈哈呀2 小时前
vue中的css深度选择器v-deep 配合!important
前端·css·vue.js
旭东怪3 小时前
EasyPoi 使用$fe:模板语法生成Word动态行
java·前端·word
ekskef_sef4 小时前
32岁前端干了8年,是继续做前端开发,还是转其它工作
前端
sunshine6415 小时前
【CSS】实现tag选中对钩样式
前端·css·css3
真滴book理喻5 小时前
Vue(四)
前端·javascript·vue.js
蜜獾云5 小时前
npm淘宝镜像
前端·npm·node.js