Provayderlar
Provayderlar Nestdagi asosiy tushuncha. Servislar, repozitoriyalar, fabrikalar va yordamchilar kabi Nestning ko'plab bazaviy sinflari provayder sifatida qaralishi mumkin. Provayder
Provayderlar Nestdagi asosiy tushuncha. Servislar, repozitoriyalar, fabrikalar va yordamchilar kabi Nestning ko'plab bazaviy sinflari provayder sifatida qaralishi mumkin. Provayderning asosiy g'oyasi shuki, u bog'liqlik sifatida in'eksiya qilinishi mumkin, bu esa obyektlarga bir-biri bilan turli munosabatlarni shakllantirish imkonini beradi. Bu obyektlarni "bog'lash" mas'uliyati asosan Nest runtime tizimi tomonidan bajariladi.
Oldingi bobda biz oddiy CatsController yaratdik. Kontrollerlar HTTP so'rovlarini qayta ishlashi va murakkabroq vazifalarni provayderlarga delegatsiya qilishi kerak. Provayderlar NestJS modulida providers sifatida e'lon qilinadigan oddiy JavaScript sinflaridir. Batafsil ma'lumot uchun "Modullar" bobiga qarang.
Nest bog'liqliklarni obyektga yo'naltirilgan tarzda loyihalash va tashkil qilish imkonini bergani uchun, biz SOLID prinsiplariga amal qilishni qat'iy tavsiya qilamiz.
Servislar
Keling, oddiy CatsService yaratishdan boshlaylik. Bu servis ma'lumotlarni saqlash va qaytarib olishni boshqaradi, va u CatsController tomonidan ishlatiladi. Ilovaning logikasini boshqarishdagi roli tufayli uni provayder sifatida aniqlash uchun ideal nomzod.
1import { Injectable } from '@nestjs/common';
2import { Cat } from './interfaces/cat.interface';
3
4@Injectable()
5export class CatsService {
6 private readonly cats: Cat[] = [];
7
8 create(cat: Cat) {
9 this.cats.push(cat);
10 }
11
12 findAll(): Cat[] {
13 return this.cats;
14 }
15}CLI orqali servis yaratish uchun shunchaki $ nest g service cats buyrug'ini bajaring.
Bizning CatsService bitta xossa va ikki metodga ega oddiy sinf. Bu yerda asosiy qo'shimcha @Injectable() dekoratori. Ushbu dekorator sinfga metadata biriktirib, CatsService Nest IoC konteyneri tomonidan boshqarilishi mumkin bo'lgan sinf ekanini bildiradi.
Shuningdek, bu misolda Cat interfeysi ishlatiladi, u taxminan quyidagicha ko'rinadi:
1export interface Cat {
2 name: string;
3 age: number;
4 breed: string;
5}Endi mushuklarni olish uchun servis sinfiga ega bo'lganimizdan so'ng, undan CatsController ichida foydalanamiz:
1import { Controller, Get, Post, Body } from '@nestjs/common';
2import { CreateCatDto } from './dto/create-cat.dto';
3import { CatsService } from './cats.service';
4import { Cat } from './interfaces/cat.interface';
5
6@Controller('cats')
7export class CatsController {
8 constructor(private catsService: CatsService) {}
9
10 @Post()
11 async create(@Body() createCatDto: CreateCatDto) {
12 this.catsService.create(createCatDto);
13 }
14
15 @Get()
16 async findAll(): Promise<Cat[]> {
17 return this.catsService.findAll();
18 }
19}CatsService sinf konstruktori orqali in'eksiya qilinadi. private kalit so'zidan foydalanilganiga e'tibor bering. Bu qisqa yozuv bir qatorda catsService a'zosini ham e'lon qilish, ham boshlang'ich qiymatini berish imkonini beradi va jarayonni soddalashtiradi.
Bog'liqliklarni in'eksiya qilish
Nest Dependency Injection deb ataladigan kuchli dizayn namunasi asosida qurilgan. Bu tushuncha haqida rasmiy Angular hujjatlari dagi ajoyib maqolani o'qishni qat'iy tavsiya qilamiz.
Nestda TypeScript imkoniyatlari tufayli bog'liqliklarni boshqarish oson, chunki ular turiga qarab yechiladi. Quyidagi misolda Nest catsService ni CatsService instansiyasini yaratib va qaytarib yechadi (yoki singleton bo'lsa, u allaqachon boshqa joyda so'ralgan bo'lsa, mavjud instansiyani qaytaradi). Bu bog'liqlik so'ng kontroller konstruktori ichiga in'eksiya qilinadi (yoki ko'rsatilgan xossaga biriktiriladi):
1constructor(private catsService: CatsService) {}Qamrovlar
Provayderlar odatda ilovaning hayot davriga mos keladigan yashash muddati ("scope") ga ega. Ilova bootstrapping qilinganda, har bir bog'liqlik yechilishi kerak, ya'ni har bir provayder instansiyalanadi. Xuddi shuningdek, ilova to'xtatilganda, barcha provayderlar yo'q qilinadi. Biroq provayderni request-scoped qilish ham mumkin, ya'ni uning yashash muddati ilovaning hayot davriga emas, balki muayyan so'rovga bog'lanadi. Bu usullar haqida In'eksiya qamrovlari bobidan ko'proq bilib olishingiz mumkin.
Maxsus provayderlar
Nest provayderlar orasidagi munosabatlarni boshqaradigan o'rnatilgan inversion of control ("IoC") konteyneri bilan keladi. Bu imkoniyat bog'liqliklarni in'eksiya qilishning poydevori, ammo u biz hozirgacha ko'rganimizdan ancha kuchli. Provayderni aniqlashning bir nechta usuli bor: oddiy qiymatlar, sinflar, hamda asinxron yoki sinxron fabrikalardan foydalanishingiz mumkin. Provayderlarni aniqlash bo'yicha ko'proq misollar uchun Bog'liqliklarni in'eksiya qilish bobini ko'ring.
Ixtiyoriy provayderlar
Ba'zan har doim ham yechilishi shart bo'lmagan bog'liqliklar bo'lishi mumkin. Masalan, sinfingiz konfiguratsiya obyektiga bog'liq bo'lishi mumkin, ammo u taqdim etilmasa, standart qiymatlar ishlatilishi kerak. Bunday holatlarda bog'liqlik ixtiyoriy hisoblanadi va konfiguratsiya provayderi bo'lmasa, xato yuzaga kelmasligi kerak.
Provayderni ixtiyoriy deb belgilash uchun konstruktor imzosida @Optional() dekoratoridan foydalaning.
1import { Injectable, Optional, Inject } from '@nestjs/common';
2
3@Injectable()
4export class HttpService<T> {
5 constructor(@Optional() @Inject('HTTP_OPTIONS') private httpClient: T) {}
6}Yuqoridagi misolda biz maxsus provayderdan foydalanmoqdamiz, shuning uchun HTTP_OPTIONS maxsus tokenini qo'shamiz. Oldingi misollarda konstruktor asosidagi in'eksiya ko'rsatilgan edi, bunda bog'liqlik konstruktorda sinf orqali ko'rsatiladi. Maxsus provayderlar va ularning tegishli tokenlari qanday ishlashi haqida ko'proq ma'lumot uchun Maxsus provayderlar bobini ko'ring.
Xossalarga asoslangan in'eksiya
Hozirgacha qo'llagan usulimiz konstruktor asosidagi in'eksiya deb ataladi, bunda provayderlar konstruktor metodi orqali in'eksiya qilinadi. Ayrim aniq holatlarda xossalarga asoslangan in'eksiya foydali bo'lishi mumkin. Masalan, yuqori darajadagi sinfingiz bir yoki bir nechta provayderga bog'liq bo'lsa, ularni quyi sinflarda super() orqali yuqorigacha uzatish noqulay bo'lib qolishi mumkin. Buni oldini olish uchun @Inject() dekoratorini bevosita xossa darajasida ishlatishingiz mumkin.
1import { Injectable, Inject } from '@nestjs/common';
2
3@Injectable()
4export class HttpService<T> {
5 @Inject('HTTP_OPTIONS')
6 private readonly httpClient: T;
7}Agar sinfingiz boshqa sinfni kengaytirmasa, odatda konstruktor asosidagi in'eksiyadan foydalanish yaxshiroq. Konstruktor qaysi bog'liqliklar kerakligini aniq ko'rsatadi, bu esa @Inject bilan belgilangan sinf xossalariga qaraganda ko'proq ko'rinish beradi va kodni tushunishni osonlashtiradi.
Provayderni ro'yxatdan o'tkazish
Endi provayder (CatsService) va iste'molchi (CatsController) ni aniqlaganimizdan so'ng, in'eksiyani bajara olishi uchun servisni Nestda ro'yxatdan o'tkazishimiz kerak. Bu modul faylini (app.module.ts) tahrirlab va servisni @Module() dekoratoridagi providers massiviga qo'shish orqali amalga oshiriladi.
1import { Module } from '@nestjs/common';
2import { CatsController } from './cats/cats.controller';
3import { CatsService } from './cats/cats.service';
4
5@Module({
6 controllers: [CatsController],
7 providers: [CatsService],
8})
9export class AppModule {}Endi Nest CatsController sinfining bog'liqliklarini yecha oladi.
Hozircha katalog tuzilmasi quyidagicha bo'lishi kerak:
Qo'lda instansiyalash
Hozirga qadar Nest bog'liqliklarni yechishdagi aksariyat tafsilotlarni avtomatik tarzda qanday boshqarishini ko'rib chiqdik. Biroq, ayrim holatlarda o'rnatilgan Dependency Injection tizimidan tashqariga chiqib, provayderlarni qo'lda olish yoki instansiyalashga ehtiyoj tug'ilishi mumkin. Shunday ikki usul quyida qisqacha bayon qilingan.
- Mavjud instansiyalarni olish yoki provayderlarni dinamik instansiyalash uchun Modulga murojaat dan foydalanishingiz mumkin.
bootstrap()funksiyasi ichida provayderlarni olish (masalan, mustaqil ilovalar uchun yoki bootstrapping jarayonida konfiguratsiya servisidan foydalanish uchun) uchun Mustaqil ilovalar sahifasiga qarang.