供应商
供应商
提供程序是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