Nest(四):Providers

譯自:https://docs.nestjs.com/providers。

Providers是Nest中的一個基本概念。許多基本的嵌套類可以被視為Providers——services、repositories、factories、helpers等等。Providers的主要思想是它可以注入依賴項;這意味著對象可以彼此創(chuàng)建各種關(guān)系,并且對象的“連接”實(shí)例的功能在很大程度上可以委托給Nest運(yùn)行時系統(tǒng)。Providers只是一個用@Injectable()裝飾器注釋的類。

image.png

在前一章中,我們構(gòu)建了一個簡單的CatsController??刂破鲬?yīng)該處理HTTP請求,并將更復(fù)雜的任務(wù)委托給Providers。提供者是純JavaScript類,在類聲明之前有一個@Injectable()裝飾器。

提示
由于Nest支持以一種更面向?qū)ο蟮姆绞皆O(shè)計和組織依賴關(guān)系,因此我們強(qiáng)烈建議遵循SOLID原則。

Services

讓我們從創(chuàng)建一個簡單的CatsService開始。該服務(wù)將負(fù)責(zé)數(shù)據(jù)存儲和檢索,并被設(shè)計為供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創(chuàng)建服務(wù),只需執(zhí)行$ nest g service cats命令。

我們的CatsService是一個基本類,有一個屬性和兩個方法。惟一的新特性是它使用@Injectable()裝飾器。@Injectable()裝飾器附加了元數(shù)據(jù),它告訴Nest這個類是一個Nest provider。順便說一下,這個例子也使用了一個Cat接口,它可能看起來像這樣:

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

現(xiàn)在我們有一個服務(wù)類來檢索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是通過類構(gòu)造函數(shù)注入的。注意使用private readonly語法。這種簡寫允許我們在同一位置立即聲明和初始化catsService成員。

Dependency injection

Nest是圍繞強(qiáng)設(shè)計模式(通常稱為依賴項注入)構(gòu)建的。我們建議閱讀在官方Angular文檔中關(guān)于這個概念的一篇很棒的文章。

在Nest中,由于TypeScript的功能,管理依賴項非常容易,因為依賴項僅通過類型解析。在下面的示例中,Nest將通過創(chuàng)建和返回catsService實(shí)例來解析catsService(或者,在單例的正常情況下,如果已經(jīng)在其他地方請求了現(xiàn)有實(shí)例,則返回它)。該依賴項被解析并傳遞給控制器的構(gòu)造函數(shù)(或分配給指定的屬性):

constructor(private readonly catsService: CatsService) {}

Scopes

Providers 通常有一個與應(yīng)用程序生命周期同步的生命周期(“范圍”)。當(dāng)應(yīng)用程序引導(dǎo)時,必須解析每個依賴項,因此必須實(shí)例化每個provider 。類似地,當(dāng)應(yīng)用程序關(guān)閉時,每個provider 都會被銷毀。但是,也有一些方法可以使您的provider 的生命周期范圍成為request-scoped。您可以在這里閱讀更多關(guān)于這些技術(shù)的信息。

Custom providers

Nest有一個內(nèi)置的控制反轉(zhuǎn)(“IoC”)容器,用于解決providers之間的關(guān)系。這個特性是上面描述的依賴注入特性的基礎(chǔ),但實(shí)際上比我們目前描述的功能強(qiáng)大得多。@Injectable()裝飾器只是冰山一角,并不是定義providers的唯一方法。實(shí)際上,您可以使用純值、類以及異步或同步工廠。這里提供了更多的例子。

Optional providers

有時候,您可能有一些不需要解決的依賴關(guān)系。例如,您的類可能依賴于configuration object,但是如果沒有傳遞,則應(yīng)該使用默認(rèn)值。在這種情況下,依賴項是可選的,因為缺少配置提供程序不會導(dǎo)致錯誤。

要指示提供程序是可選的,請在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的原因。前面的示例顯示了基于構(gòu)造函數(shù)的注入,它通過構(gòu)造函數(shù)中的類指示依賴關(guān)系。有關(guān)自定義提供程序及其關(guān)聯(lián)令牌的更多信息,請在這里閱讀。

Property-based injection

我們目前使用的技術(shù)稱為基于構(gòu)造函數(shù)的注入,因為提供者是通過構(gòu)造函數(shù)方法注入的。在某些非常特殊的情況下,property-based injection可能是有用的。例如,如果您的頂級類依賴于一個或多個提供者,那么通過在構(gòu)造函數(shù)的子類中調(diào)用super()來傳遞它們將非常單調(diào)乏味。為了避免這種情況,您可以在屬性級別使用@Inject()裝飾器。

import { Injectable, Inject } from '@nestjs/common';

@Injectable()
export class HttpService<T> {
  @Inject('HTTP_OPTIONS')
  private readonly httpClient: T;
}

警告
如果您的類不擴(kuò)展其他提供程序,您應(yīng)該始終選擇使用constructor-based的注入。

Provider registration

現(xiàn)在我們已經(jīng)定義了一個provider (CatsService),并且有了該服務(wù)的消費(fèi)者(CatsController),我們需要向Nest注冊該服務(wù),以便它能夠執(zhí)行注入。我們通過編輯模塊文件(app.module.ts)并將服務(wù)添加到@Module()裝飾器的providers數(shù)組中來實(shí)現(xiàn)這一點(diǎn)。

// 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現(xiàn)在將能夠解決CatsController類的依賴關(guān)系。

下面是我們的目錄結(jié)構(gòu):


image.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 依賴注入(DI -- Dependency Injection)是一種重要的應(yīng)用設(shè)計模式。Angular里面...
    tuacy閱讀 13,421評論 4 16
  • 版本:Angular 5.0.0-alpha 依賴注入是重要的應(yīng)用設(shè)計模式。它使用得非常廣泛,以至于幾乎每個人都稱...
    soojade閱讀 3,062評論 0 3
  • core package 概要:Core是所有其他包的基礎(chǔ)包.它提供了大部分功能包括metadata,templa...
    LOVE小狼閱讀 2,872評論 0 3
  • 今天的主題不是雀巢咖啡,也不是雀巢奶粉,畢竟我王境澤就是餓死,也不會打你們一點(diǎn)廣告。 前言 近幾年由于 Node....
    維特陳先森閱讀 3,053評論 4 8
  • 一、什么是依賴注入 控制反轉(zhuǎn)(IoC) 控制反轉(zhuǎn)的概念最早在2004年由Martin Fowler提出,是針對面向...
    Keriy閱讀 3,572評論 0 8

友情鏈接更多精彩內(nèi)容