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:
1@Injectable()
2export class CatsService {
3 constructor(private moduleRef: ModuleRef) {}
4}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.
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}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.
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.
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.
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.
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}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:
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.
1@Injectable()
2export class CatsService {
3 constructor(
4 @Inject(REQUEST) private request: Record<string, unknown>,
5 ) {}
6}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:
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.
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.