上篇文章我們學習瞭如何使用nest-cli
來快速生成一個NestJS
後端專案,當我們開啟編輯器檢視程式碼時,會發現整個程式碼風格有點類似JAVA的spring
框架,並且你會發現一些service
類在controller
控制器的constructor
中注入後,可以不需要手動new
就可以直接使用該類對應的實體方法。
比如:
import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';
@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}
@Get('/hello')
get(): string {
return this.appService.getHello();
}
}
這其實就是Nest
依賴注入與控制反轉,目的主要是方便程式碼之間的解耦從而減少維護成本。
這兩個概念不要搞混了,IOC其實是物件導向程式設計中的一種設計模式,而DI則是為了實現IOC的一種技術。
比如,我們有兩個類,它們之間存在耦合關係,我們一般會這樣寫:
// A.ts
class A {
name: string
constructor(name: string) {
this.name = name
}
}
// B.ts
class B {
age: number
name: A
constructor(age: number) {
this.age = age
this.name = new A('南玖')
}
}
// main.ts
const b = new B(18)
console.log(b)
當我們遇到類與類之間存在依賴關係時,一般會直接在類的內部建立依賴物件,這樣就會導致各個類之間形成耦合,並且這種關係會隨著依賴關係越來越複雜從而耦合度也會越來越高,最終造成程式碼的難以維護。
為了解決上面程式碼帶來的耦合性問題,我們可以使用IOC容器來進行管理
// container.ts
export class Container {
modules = new Map()
// 註冊範例
provide(key: string, clazz: any, argvs: Array<any>) {
this.modules.set(key, {clazz, argvs})
}
// 獲取範例
get(key: string) {
const {clazz, argvs} = this.modules.get(key)
return Reflect.construct(clazz, argvs)
}
}
這裡的Reflect.construct
是為了幫我們範例化一個物件。
以上就是容器化思路,統一管理,可以實現類與類之間的解耦。
依賴注入是一種控制反轉
IOC(inversion of control)
技術,就是你可以把物件或依賴的範例化交給IOC
容器去處理,在NestJS
中這個容器就是NestJS
的執行時系統。當需要一個物件範例的時候,我們不需要自己手動new xxxClass()
,只需要在合適的地方對類進行註冊,在需要用到的地方直接注入,容器將為我們完成new
的動作
在Nest
中使用依賴注入一般有以下三步:
使用@Injectable
裝飾器來宣告一個類,它表示該類可以由Nest
的IOC
容器管理
// app.service.ts
import { Injectable } from '@nestjs/common';
@Injectable()
export class AppService {
getHello(): string {
return 'Hello nanjiu';
}
}
這是依賴注入的地方,一般是在類別建構函式constructor
中注入,只有完成注入後才可以使用
// app.controller.ts
import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';
@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}
@Get('/hello')
get(): string {
return this.appService.getHello();
}
}
官方把appService
稱為token
,NestJS
會根據這個token
在容器中找到第1步中宣告的類(這個對應關係將在第三步中進行關聯註冊),從而提供對應的範例,這裡的範例全域性唯一,只有1個!在第一次需要該範例的時候,Nest
會new
一個出來,而後會快取起來,後序如果其它地方也注入了這個依賴,那Nest
會從快取中拿到之前new
出來的範例供大家使用。
依賴注入後還需要在Module
中進行關聯
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
@Module({
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
Nest
會根據所有注入的依賴關係生成一個依賴關係圖,就有點類似我們使用import
引入各個模組時也會生成一個複雜的依賴關係圖。這裡AppController
中依賴了AppService
,如果AppService
中還依賴其它東西也會一併放到Nest
構建的依賴關係圖中,Nest
會從下到上按照依賴順序構建出一整張依賴關係圖保證所有的依賴關係正常運作。
-------------------------------------------
如果這篇文章有幫助到你,❤️關注+點贊❤️鼓勵一下作者,文章公眾號首發,關注 前端南玖 第一時間獲取最新的文章~
掃描下方二維條碼關注公眾號,回覆進群,拉你進前端學習交流群