W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
來自不同語言背景的開發(fā)者,在學習Nest時可能預料不到在請求中幾乎所有內(nèi)容都是共享的。我們建立一個連接池到數(shù)據(jù)庫,在全局狀態(tài)下使用單例服務。 要記住Node.js并不遵循多線程下請求/響應的無狀態(tài)模式。因此,在我們的應用中使用單例是安全的。
然而,在需要考慮請求生命周期的情況下,存在邊緣情況.例如,在GraphQL應用的預請求緩存中,以及請求追蹤和多租戶條件下,注入作用域提供了一個機制來獲取需要的提供者生命周期行為.
基本上,每個提供者都可以作為一個單例,被請求范圍限定,并切換到瞬態(tài)模式。請參見下表,以熟悉它們之間的區(qū)別。
DEFAULT | 每個提供者可以跨多個類共享。提供者生命周期嚴格綁定到應用程序生命周期。一旦應用程序啟動,所有提供程序都已實例化。默認情況下使用單例范圍。 |
REQUEST | 在請求處理完成后,將為每個傳入請求和垃圾收集專門創(chuàng)建提供者的新實例 |
TRANSIENT | 臨時提供者不能在提供者之間共享。每當其他提供者向 Nest 容器請求特定的臨時提供者時,該容器將創(chuàng)建一個新的專用實例 |
使用單例范圍始終是推薦的方法。請求之間共享提供者可以降低內(nèi)存消耗,從而提高應用程序的性能(不需要每次實例化類)。
為了切換到另一個注入范圍,您必須向 @Injectable() 裝飾器傳遞一個選項對象。
import { Injectable, Scope } from '@nestjs/common';
@Injectable({ scope: Scope.REQUEST })
export class CatsService {}
在自定義提供者的情況下,您必須設置一個額外的范圍屬性。
{
provide: 'CACHE_MANAGER',
useClass: CacheManager,
scope: Scope.TRANSIENT,
}
Scope從@nestjs/common中導入。
網(wǎng)關不應該使用請求范圍提供者,因為其必須作為單例提供。每個網(wǎng)關都封裝了一個socket并且不能多次實例化。
默認使用單例范圍,并且不需要聲明。如果你想聲明一個單例范圍的提供者,在scope屬性中使用Scope.DEFAULT值。
當涉及到控制器時,傳遞 ControllerOptions 對象
@Controller({
path: 'cats',
scope: Scope.REQUEST,
})
export class CatsController {}
網(wǎng)關永遠不應該依賴于請求范圍的提供者,因為它們充當單例。一個網(wǎng)關封裝了一個真正的套接字,不能多次被實例化
必須非常謹慎地使用請求范圍的提供者。請記住,scope 實際上是在注入鏈中冒泡的。如果您的控制器依賴于一個請求范圍的提供者,這意味著您的控制器實際上也是請求范圍。
想象一下下面的鏈: CatsController <- CatsService <- CatsRepository 。如果您的 CatsService 是請求范圍的(從理論上講,其余的都是單例),那么 CatsController 也將成為請求范圍的(因為必須將請求范圍的實例注入到新創(chuàng)建的控制器中),而 CatsRepository 仍然是單例的。
在這種情況下,循環(huán)依賴關系將導致非常痛苦的副作用,因此,您當然應該避免創(chuàng)建它們
在 HTTP 應用程序中(例如使用@nestjs/platform-express或@nestjs/platform-fastify),當使用請求范圍提供者時,可能需要獲取原始的請求對象。這通過注入REQUEST對象實現(xiàn):
import { Injectable, Scope, Inject } from '@nestjs/common';
import { REQUEST } from '@nestjs/core';
import { Request } from 'express';
@Injectable({ scope: Scope.REQUEST })
export class CatsService {
constructor(@Inject(REQUEST) private readonly request: Request) {}
}
由于底層平臺和協(xié)議不同,該功能與微服務和 GraphQL 應用程序略有不同。在 GraphQL 應用程序中,可以注入 CONTEXT來替代REQUEST。
import { Injectable, Scope, Inject } from '@nestjs/common';
import { CONTEXT } from '@nestjs/graphql';
@Injectable({ scope: Scope.REQUEST })
export class CatsService {
constructor(@Inject(CONTEXT) private readonly context) {}
}
然后,您可以配置您的 context 值(在GraphQLModule中),以包含請求作為其屬性。
使用請求范圍的提供者將明顯影響應用程序性能。即使 Nest 試圖緩存盡可能多的元數(shù)據(jù),它仍然必須為每個請求創(chuàng)建類的實例。因此,它將降低您的平均響應時間和總體基準測試結果。如果您的提供者不一定需要請求范圍,那么您應該堅持使用單例范圍。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: