10

《Nest 通关秘籍》学习nest笔记 Provide注入、循环依赖、动态Module

 1 year ago
source link: https://www.daozhao.com/10930.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

《Nest 通关秘籍》学习nest笔记 Provide注入、循环依赖、动态Module

如果您发现本文排版有问题,可以先点击下面的链接切换至老版进行查看!!!

《Nest 通关秘籍》学习nest笔记 Provide注入、循环依赖、动态Module

灵活的Provide注入

在 Module 的 providers 里声明:

file

其实这是一种简写,完整的写法是这样的:

file

通过 provide 指定注入的 token,通过 useClass 指定注入的对象的类,Nest 会自动对它做实例化再注入。

file

如果不想用构造器注入,也可以属性注入:

file

通过 @Inject 指定注入的 provider 的 token 即可。 当然,这个 token 也可以是字符串:

file

如果 token 是字符串的话,注入的时候就要用 @Inject 手动指定注入对象的 token 了:

file

调试一下,确实也注入了的。

Module、Service循环依赖怎么办

其实我们可以先单独创建这两个 Module,然后再让两者关联起来。

也就是用 forwardRef 的方式:

file

动态Module

有的时候我们希望 import 的时候给这个模块传一些参数,动态生成模块的内容,怎么办呢?

这时候就需要 Dynamic Module 了:

import { DynamicModule, Module } from '@nestjs/common';
import { BbbService } from './bbb.service';
import { BbbController } from './bbb.controller';

@Module({})
export class BbbModule {

  static register(options: Record<string, any>): DynamicModule {
    return {
      module: BbbModule, // !!! 和在装饰器里定义的时候的区别,只是多了一个 module 属性
      controllers: [BbbController],
      providers: [
        {
          provide: 'CONFIG_OPTIONS', // !!!
          useValue: options,
        },
        BbbService,
      ],
      exports: []
    };
  }
}

而且我们还可以把参数传入的 options 对象作为一个新的 provider。

import 的时候就得这样用了,通过 register 方法传入参数,返回值就是模块定义

file

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

file

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

  • register
  • forRoot
  • forFeature

我们约定它们分别用来做不同的事情:

  • register:用一次模块传一次配置,比如这次调用是 BbbModule.register({aaa:1}),下一次就是 BbbModule.register({aaa:2}) 了

  • forRoot:配置一次模块用多次,比如 XxxModule.forRoot({}) 一次,之后就一直用这个 Module,一般在 AppModule 里 import

  • forFeature:用了 forRoot 固定了整体模块,用于局部的时候,可能需要再传一些配置,比如用 forRoot 指定了数据库链接信息,再用 forFeature 指定某个模块访问哪个数据库和表。

这次我们也可以不手动写 register等方法,用 builder 来生成。

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

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

export interface CccModuleOptions {
    aaa: number;
    bbb: string;
}

export const { ConfigurableModuleClass, MODULE_OPTIONS_TOKEN } =
  new ConfigurableModuleBuilder<CccModuleOptions>().build();

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

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

然后 Module 继承它:

file

这样这个 CccModule 就已经有了 register 和 registerAsync 方法了。

不用自己定义了,省事了不少。

传入 options:

file

那现在如何在 Module 内注入这个 options 呢?

记得 build class 的时候返回了一个 tokenMODULE_OPTIONS_TOKEN么? 将它注入即可

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

@Controller('ccc')
export class CccController {

    @Inject(MODULE_OPTIONS_TOKEN)
    private options: CccModuleOptions;

    @Get('')
    hello() {
        return this.options; // 即为{aaa: 1, bbb: 'bbb'}
    }
}

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK