在线文档教程

供应商

供应商

提供程序是Nest的基本概念。许多基本的Nest类都可以被视为提供者(provider) - 服务(service),存储库(repository),工厂(factory),帮助器(helper)等等。所有这些都可以通过注入依赖关系constructor,这意味着它们可以相互创建各种关系。但事实上,提供者(provider)只不过是一个用@Injectable()装饰器注释的简单类。

在前一章中,我们构建了一个简单的CatsController。控制器应处理HTTP请求并将更复杂的任务委托给服务。提供程序是纯JavaScript类,@Injectable()在它们之上有一个装饰器。

提示由于Nest支持以更OO方式设计和组织依赖项的可能性,因此我们强烈建议遵循SOLID原则。

服务

让我们从创建一个简单的CatsService提供者开始。该服务将负责数据的存储和检索,并且被设计为由所使用CatsController,因此,将其定义为提供者是一个很好的选择。

cats.service.ts

JS

import { Injectable } from '@nestjs/common'; import { Cat } from './interfaces/cat.interface'; @Injectable() export class CatsService { private readonly cats: Cat[] = []; create(cat: Cat) { this.cats.push(cat } findAll(): Cat[] { return this.cats; } }

提示要使用CLI创建服务,只需执行$ nest g service cats/cats命令即可。

这是一个CatsService基本类,有一个属性和两个方法。唯一的新特性是它使用@Injectable()装饰器。该@Injectable()附加的元数据,从而使Nest知道这个类是一个Nest provider。请注意,Cat上面使用了一个接口。我们没有提到它,因为模式与CreateCatDto我们在前一章中创建的类完全相同。

既然我们已经完成了服务类,那么让我们在以下内容中使用它CatsController

cats.controller.ts

JS

import { Controller, Get, Post, Body } from '@nestjs/common'; import { CreateCatDto } from './dto/create-cat.dto'; import { CatsService } from './cats.service'; import { Cat } from './interfaces/cat.interface'; @Controller('cats') export class CatsController { constructor(private readonly catsService: CatsService) {} @Post() async create(@Body() createCatDto: CreateCatDto) { this.catsService.create(createCatDto } @Get() async findAll(): Promise<Cat[]> { return this.catsService.findAll( } }

CatsService注入通过类的构造函数。注意private语法的使用。这个简写允许我们catsService在同一位置立即声明和初始化成员。

依赖注入

Nest是围绕着强大的设计模式(通常称为“依赖注入”)构建的。我们建议在Angular官方文档中阅读关于此概念的精彩文章。

在Nest中,由于具有TypeScript功能,管理依赖关系非常容易,因为它们仅按类型进行解析。在下面的示例中,Nest将catsService通过创建并返回的实例CatsService(或在单例的正常情况下,如果已在其他地方请求了现有的实例,则返回该实例)来解决。此依赖关系已解决,并传递给控制器​​的构造函数(或分配给指定的属性):

constructor(private readonly catsService: CatsService) {}

定制供应商

控制容器的反转(Nest用于解决提供者之间的关系)比上面描述的要强大得多。@Injectable()装饰仅是冰山一角,没有严格要求,以限定提供商的前端。相反,您可以使用普通值,类,异步或同步工厂。看这里找到更多的例子。

可选提供商

有时,您可能具有不一定必须解决的依赖关系。例如,您的类可能依赖于配置对象,但是如果未传递任何配置对象,则应使用默认值。在这种情况下,依赖项变为可选的,因为缺少配置提供程序不会导致错误。

要指示提供程序是可选的,请@Optional()在构造函数的签名中使用装饰器。

import { Injectable, Optional } from '@nestjs/common'; @Injectable() export class HttpService { constructor( @Optional() @Inject('HTTP_OPTIONS') private readonly httpClient, ) {} }

范围

最后一件事是告诉模块CatsService真正存在的东西。我们通过编辑模块文件来完成此操作app.module.ts,并将服务放入装饰器的providers数组中@Module()

app.module.ts

JS

import { Module } from '@nestjs/common'; import { CatsController } from './cats/cats.controller'; import { CatsService } from './cats/cats.service'; @Module{ controllers: [CatsController], providers: [CatsService], }) export class ApplicationModule {}

多亏了这一点,Nest将能够解决CatsController该类的依赖关系。这就是我们的目录结构现在的样子:

SRC

DTO

创建-cat.dto.ts

接口

cat.interface.ts

cats.service.ts

cats.controller.ts

app.module.ts

main.ts