美文网首页
Nest(四):Providers

Nest(四):Providers

作者: real_ting | 来源:发表于2019-06-19 11:40 被阅读0次

    译自:https://docs.nestjs.com/providers

    Providers是Nest中的一个基本概念。许多基本的嵌套类可以被视为Providers——services、repositories、factories、helpers等等。Providers的主要思想是它可以注入依赖项;这意味着对象可以彼此创建各种关系,并且对象的“连接”实例的功能在很大程度上可以委托给Nest运行时系统。Providers只是一个用@Injectable()装饰器注释的类。

    image.png

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

    提示
    由于Nest支持以一种更面向对象的方式设计和组织依赖关系,因此我们强烈建议遵循SOLID原则。

    Services

    让我们从创建一个简单的CatsService开始。该服务将负责数据存储和检索,并被设计为供CatsController使用,因此它是一个很好的候选Providers。因此,我们使用@Injectable()装饰类。

    // cats.service.ts
    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命令。

    我们的CatsService是一个基本类,有一个属性和两个方法。惟一的新特性是它使用@Injectable()装饰器。@Injectable()装饰器附加了元数据,它告诉Nest这个类是一个Nest provider。顺便说一下,这个例子也使用了一个Cat接口,它可能看起来像这样:

    export interface Cat {
      name: string;
      age: number;
      breed: string;
    }
    

    现在我们有一个服务类来检索cats,让我们在CatsController中使用它:

    // cats.controller.ts
    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 readonly语法。这种简写允许我们在同一位置立即声明和初始化catsService成员。

    Dependency injection

    Nest是围绕强设计模式(通常称为依赖项注入)构建的。我们建议阅读在官方Angular文档中关于这个概念的一篇很棒的文章。

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

    constructor(private readonly catsService: CatsService) {}
    

    Scopes

    Providers 通常有一个与应用程序生命周期同步的生命周期(“范围”)。当应用程序引导时,必须解析每个依赖项,因此必须实例化每个provider 。类似地,当应用程序关闭时,每个provider 都会被销毁。但是,也有一些方法可以使您的provider 的生命周期范围成为request-scoped。您可以在这里阅读更多关于这些技术的信息。

    Custom providers

    Nest有一个内置的控制反转(“IoC”)容器,用于解决providers之间的关系。这个特性是上面描述的依赖注入特性的基础,但实际上比我们目前描述的功能强大得多。@Injectable()装饰器只是冰山一角,并不是定义providers的唯一方法。实际上,您可以使用纯值、类以及异步或同步工厂。这里提供了更多的例子。

    Optional providers

    有时候,您可能有一些不需要解决的依赖关系。例如,您的类可能依赖于configuration object,但是如果没有传递,则应该使用默认值。在这种情况下,依赖项是可选的,因为缺少配置提供程序不会导致错误。

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

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

    注意,在上面的示例中,我们使用的是自定义提供程序,这就是我们包含HTTP_OPTIONS自定义token的原因。前面的示例显示了基于构造函数的注入,它通过构造函数中的类指示依赖关系。有关自定义提供程序及其关联令牌的更多信息,请在这里阅读。

    Property-based injection

    我们目前使用的技术称为基于构造函数的注入,因为提供者是通过构造函数方法注入的。在某些非常特殊的情况下,property-based injection可能是有用的。例如,如果您的顶级类依赖于一个或多个提供者,那么通过在构造函数的子类中调用super()来传递它们将非常单调乏味。为了避免这种情况,您可以在属性级别使用@Inject()装饰器。

    import { Injectable, Inject } from '@nestjs/common';
    
    @Injectable()
    export class HttpService<T> {
      @Inject('HTTP_OPTIONS')
      private readonly httpClient: T;
    }
    

    警告
    如果您的类不扩展其他提供程序,您应该始终选择使用constructor-based的注入。

    Provider registration

    现在我们已经定义了一个provider (CatsService),并且有了该服务的消费者(CatsController),我们需要向Nest注册该服务,以便它能够执行注入。我们通过编辑模块文件(app.module.ts)并将服务添加到@Module()装饰器的providers数组中来实现这一点。

    // app.module.ts
    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类的依赖关系。

    下面是我们的目录结构:


    image.png

    相关文章

      网友评论

          本文标题:Nest(四):Providers

          本文链接:https://www.haomeiwen.com/subject/qgjqqctx.html