Asosiy tushunchalar4 min read

Modulga murojaat

Nest provayderlarning ichki ro'yxatini ko'rib chiqish va in'eksiya tokeni bo'yicha istalgan provayderga havola olish uchun ModuleRef sinfini taqdim etadi. ModuleRef sinfi statik va

Nest provayderlarning ichki ro'yxatini ko'rib chiqish va in'eksiya tokeni bo'yicha istalgan provayderga havola olish uchun ModuleRef sinfini taqdim etadi. ModuleRef sinfi statik va scoped provayderlarni dinamik instansiyalash yo'lini ham taqdim etadi. ModuleRef ni odatdagi tarzda sinfga in'eksiya qilish mumkin:

TypeScript
cats.service
1@Injectable()
2export class CatsService {
3  constructor(private moduleRef: ModuleRef) {}
4}
Hint

ModuleRef sinfi @nestjs/core paketidan import qilinadi.

Instansiyalarni olish

ModuleRef instansiyasi (keyingi o'rinlarda modulga murojaat deb ataymiz) get() metodiga ega. Standart holatda bu metod joriy modulda ro'yxatdan o'tgan va instansiyalangan provayderni, controllerni yoki injectable ni (masalan, guard, interceptor va hokazo) uning in'eksiya tokeni/sinf nomi bo'yicha qaytaradi. Agar instansiya topilmasa, istisno tashlanadi.

TypeScript
cats.service
1@Injectable()
2export class CatsService implements OnModuleInit {
3  private service: Service;
4  constructor(private moduleRef: ModuleRef) {}
5
6  onModuleInit() {
7    this.service = this.moduleRef.get(Service);
8  }
9}
Warning

get() metodi bilan scoped provayderlarni (transient yoki request-scoped) olish mumkin emas. Buning o'rniga, quyida ta'riflangan usuldan foydalaning. Scope'larni qanday boshqarishni bu yerda bilib oling.

Global kontekstdan provayderni olish uchun (masalan, provayder boshqa modulda in'eksiya qilingan bo'lsa), get() metodining ikkinchi argumenti sifatida {{ '{' }} strict: false {{ '}' }} opsiyasini uzating.

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

Scoped provayderlarni yechish

Scoped provayderni (transient yoki request-scoped) dinamik yechish uchun resolve() metodidan foydalaning va provayderning in'eksiya tokenini argument sifatida uzating.

TypeScript
cats.service
1@Injectable()
2export class CatsService implements OnModuleInit {
3  private transientService: TransientService;
4  constructor(private moduleRef: ModuleRef) {}
5
6  async onModuleInit() {
7    this.transientService = await this.moduleRef.resolve(TransientService);
8  }
9}

resolve() metodi provayderning noyob instansiyasini, uning DI container sub-tree sidan qaytaradi. Har bir sub-tree uchun noyob context identifier mavjud. Shuning uchun bu metodni bir necha marta chaqirib, instansiya havolalarini solishtirsangiz, ular teng emasligini ko'rasiz.

TypeScript
cats.service
1@Injectable()
2export class CatsService implements OnModuleInit {
3  constructor(private moduleRef: ModuleRef) {}
4
5  async onModuleInit() {
6    const transientServices = await Promise.all([
7      this.moduleRef.resolve(TransientService),
8      this.moduleRef.resolve(TransientService),
9    ]);
10    console.log(transientServices[0] === transientServices[1]); // false
11  }
12}

Bir nechta resolve() chaqiruvlari bo'ylab bitta instansiyani generatsiya qilish va ular bir xil DI container sub-tree'ni bo'lishishini ta'minlash uchun resolve() metodiga context identifier uzatishingiz mumkin. Context identifier generatsiya qilish uchun ContextIdFactory sinfidan foydalaning. Bu sinf mos noyob identifikator qaytaradigan create() metodini taqdim etadi.

TypeScript
cats.service
1@Injectable()
2export class CatsService implements OnModuleInit {
3  constructor(private moduleRef: ModuleRef) {}
4
5  async onModuleInit() {
6    const contextId = ContextIdFactory.create();
7    const transientServices = await Promise.all([
8      this.moduleRef.resolve(TransientService, contextId),
9      this.moduleRef.resolve(TransientService, contextId),
10    ]);
11    console.log(transientServices[0] === transientServices[1]); // true
12  }
13}
Hint

ContextIdFactory sinfi @nestjs/core paketidan import qilinadi.

REQUEST provayderini ro'yxatdan o'tkazish

ContextIdFactory.create() bilan qo'lda yaratilgan context identifierlar DI sub-tree'larini ifodalaydi, ularda REQUEST provayderi undefined bo'ladi, chunki ular Nest dependency injection tizimi tomonidan instansiyalanmaydi va boshqarilmaydi.

Qo'lda yaratilgan DI sub-tree uchun maxsus REQUEST obyektini ro'yxatdan o'tkazish uchun ModuleRef#registerRequestByContextId() metodidan foydalaning, quyidagicha:

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

Joriy sub-tree ni olish

Ba'zan request context ichida request-scoped provayder instansiyasini yechishingiz kerak bo'lishi mumkin. Masalan, CatsService request-scoped va siz CatsRepository instansiyasini yechmoqchisiz, u ham request-scoped provayder sifatida belgilangan. Bir xil DI container sub-tree'ni bo'lishish uchun yangi context identifier yaratish o'rniga (masalan, yuqorida ko'rsatilgandek ContextIdFactory.create() bilan), joriy context identifierni olish kerak. Joriy context identifierni olish uchun @Inject() dekoratori yordamida request obyektini in'eksiya qilishdan boshlang.

TypeScript
cats.service
1@Injectable()
2export class CatsService {
3  constructor(
4    @Inject(REQUEST) private request: Record<string, unknown>,
5  ) {}
6}
Hint

Request provayderi haqida batafsil bu yerda o'qing.

Endi ContextIdFactory sinfining getByRequest() metodidan foydalanib request obyektiga asoslangan context id yarating va buni resolve() chaqiruviga uzating:

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

Maxsus sinflarni dinamik instansiyalash

Avval provayder sifatida ro'yxatdan o'tkazilmagan sinfni dinamik instansiyalash uchun modulga murojaatning create() metodidan foydalaning.

TypeScript
cats.service
1@Injectable()
2export class CatsService implements OnModuleInit {
3  private catsFactory: CatsFactory;
4  constructor(private moduleRef: ModuleRef) {}
5
6  async onModuleInit() {
7    this.catsFactory = await this.moduleRef.create(CatsFactory);
8  }
9}

Bu texnika freymvork konteyneridan tashqarida turli sinflarni shartli instansiyalashga imkon beradi.