NestJS 模塊參考

2023-09-08 14:44 更新

Nest提供了一個(gè)ModuleRef類來導(dǎo)航到內(nèi)部提供者列表,并使用注入令牌作為查找鍵名來獲取一個(gè)引用。ModuleRef類也提供了一個(gè)動(dòng)態(tài)實(shí)例化靜態(tài)和范圍的提供者的方法。ModuleRef可以通過常規(guī)方法注入到類中:

cats.service.ts
@Injectable()
export class CatsService {
  constructor(private moduleRef: ModuleRef) {}
}

ModuleRef從@nestjs/core中引入。

獲取實(shí)例

ModuleRef實(shí)例(下文稱為模塊引用) 擁有g(shù)et()方法。該方法獲取一個(gè)提供者,控制器或者通過注入令牌/類名獲取一個(gè)在當(dāng)前模塊中可注入對(duì)象(例如守衛(wèi)或攔截器等)。

cats.service.ts
@Injectable()
export class CatsService implements OnModuleInit {
  private service: Service;
  constructor(private moduleRef: ModuleRef) {}

  onModuleInit() {
    this.service = this.moduleRef.get(Service);
  }
}

不能通過get()方法獲取一個(gè)范圍的提供者(暫態(tài)的或者請(qǐng)求范圍的)。要使用下列的技術(shù),參考這里了解更多控制范圍。

要從全局上下文獲取一個(gè)提供者(例如,如果提供者在不同模塊中注入),向get()的第二個(gè)參數(shù)傳遞{ strict: false }選項(xiàng)。

this.moduleRef.get(Service, { strict: false });

處理范圍提供者

要?jiǎng)討B(tài)處理一個(gè)范圍提供者(瞬態(tài)的或請(qǐng)求范圍的),使用resolve()方法并將提供者的注入令牌作為參數(shù)提供給方法。

cats.service.ts
@Injectable()
export class CatsService implements OnModuleInit {
  private transientService: TransientService;
  constructor(private moduleRef: ModuleRef) {}

  async onModuleInit() {
    this.transientService = await this.moduleRef.resolve(TransientService);
  }
}

resolve()方法從其自身的注入容器樹返回一個(gè)提供者的唯一實(shí)例。每個(gè)子樹都有一個(gè)獨(dú)一無二的上下文引用。因此如果你調(diào)用該方法一次以上并進(jìn)行引用比較的話,結(jié)果是不同的。

cats.service.ts
@Injectable()
export class CatsService implements OnModuleInit {
  constructor(private moduleRef: ModuleRef) {}

  async onModuleInit() {
    const transientServices = await Promise.all([
      this.moduleRef.resolve(TransientService),
      this.moduleRef.resolve(TransientService),
    ]);
    console.log(transientServices[0] === transientServices[1]); // false
  }
}

要在不同的resolve()調(diào)用之間產(chǎn)生一個(gè)單例,并保證他們共享同樣生成的DI容器子樹,向resolve()方法傳遞一個(gè)上下文引用,使用ContextIdFactory類來生成上下文引用。該類提供了一個(gè)create()方法,返回一個(gè)合適的獨(dú)一無二的引用。

cats.service.ts
@Injectable()
export class CatsService implements OnModuleInit {
  constructor(private moduleRef: ModuleRef) {}

  async onModuleInit() {
    const contextId = ContextIdFactory.create();
    const transientServices = await Promise.all([
      this.moduleRef.resolve(TransientService, contextId),
      this.moduleRef.resolve(TransientService, contextId),
    ]);
    console.log(transientServices[0] === transientServices[1]); // true
  }
}

ContextIdFactory類從@nestjs/core包中引入。

注冊(cè)REQUEST提供者

Manually generated context identifiers (with ContextIdFactory.create()) represent DI sub-trees in which REQUEST provider is undefined as they are not instantiated and managed by the Nest dependency injection system.

To register a custom REQUEST object for a manually created DI sub-tree, use the ModuleRef#registerRequestByContextId() method, as follows:

const contextId = ContextIdFactory.create();
this.moduleRef.registerRequestByContextId(/* YOUR_REQUEST_OBJECT */, contextId);

獲取當(dāng)前子樹

有時(shí),也需要在請(qǐng)求上下文中獲取一個(gè)請(qǐng)求范圍提供者的實(shí)例。例如,CatsService是請(qǐng)求范圍的,要獲取的CatsRepository實(shí)例也被標(biāo)識(shí)為請(qǐng)求范圍。要分享同一個(gè)注入容器子樹,你需要獲取當(dāng)前上下文引用而不是生成一個(gè)新的(像前面的ContextIdFactory.create()函數(shù))。使用@Inject()來獲取當(dāng)前的請(qǐng)求對(duì)象。

cats.service.ts
@Injectable()
export class CatsService {
  constructor(
    @Inject(REQUEST) private request: Record<string, unknown>,
  ) {}
}

這里了解更多請(qǐng)求提供者

使用ContextIdFactory類的getByRequest()方法來基于請(qǐng)求對(duì)象創(chuàng)建一個(gè)上下文id 并傳遞resolve()調(diào)用:

const contextId = ContextIdFactory.getByRequest(this.request);
const catsRepository = await this.moduleRef.resolve(CatsRepository, contextId);

動(dòng)態(tài)實(shí)例化自定義類

要?jiǎng)討B(tài)實(shí)例化一個(gè)之前未注冊(cè)的類作為提供者,使用模塊引用的create()方法。

cats.service.ts
@Injectable()
export class CatsService implements OnModuleInit {
  private catsFactory: CatsFactory;
  constructor(private moduleRef: ModuleRef) {}

  async onModuleInit() {
    this.catsFactory = await this.moduleRef.create(CatsFactory);
  }
}

該技術(shù)允許你在框架容器之外偶然實(shí)例化一個(gè)不同的類。


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)