Angular Dependency Injection
Bugun ushbu maqola orqali siz Angular’da Dependency Injection qanday ishlashini sodda va tushunarli tarzda bilib olasiz.
Dependency Injection’ning asosiy maqsadi — bizga kerak bo‘lgan obyektlarni o‘zimiz qo‘lda yaratmasdan, tayyor holatda Angular orqali olib ishlatishdir. Shu orqali biz class’larni bir-biridan mustaqil (loosely coupled) qilamiz va kodimiz yanada toza hamda boshqarilishi oson bo‘ladi.
Angular’da Dependency Injection yaratish uchun @Injectable decorator’idan foydalaniladi:
@Injectable({
providedIn: 'root'
})
export class Service {}Bu kod orqali biz Service’ni Angular’ning DI tizimiga ro‘yxatdan o‘tkazdik.
providedIn: 'root' degani – ushbu service butun loyiha bo‘ylab yagona instance sifatida ishlaydi va uni project’ning istalgan joyida ishlatish mumkin bo‘ladi.
Bu service’ni component ichida quyidagicha chaqiramiz:
constructor(private service: Service) {}Yoki Angular 14+ versiyalaridan boshlab inject() funksiyasi orqali ham ishlatish mumkin:
private service = inject(Service);Ikkala usul ham bir xil ishlaydi. Faqat:
- Constructor orqali chaqirish usuli Angular 14’dan oldingi versiyalarda asosiy yo‘l edi.
- Angular 14’dan keyin esa
inject()orqali ishlatish ham qo‘shildi va yanada qulay bo‘ldi.
Agar biz providedIn: 'root' ni yozmasak:
@Injectable()
export class Service {}Bu holatda biz Angular’ga shunchaki:
“Service degan class bor, agar kerak bo‘lsa yaratib berasan”,
deb aytgan bo‘lamiz. Lekin Angular qayerda uni yaratishini bilmaydi.
Agar shu service’ni component’da ishlatishga harakat qilsak, quyidagi xato chiqadi:
NullInjectorError: No provider for Service
Buni to‘g‘rilash uchun service’ni component’ning providers qismida ko‘rsatishimiz kerak:
@Component({
selector: 'app-root',
template: '',
providers: [Service]
})
export class AppComponent {}Bu yerda biz Angular’ga shunday dedik:
“Service faqat shu component va uning bolalari (child component’lari) uchun mavjud bo‘lsin.”
Ya’ni:
AppComponentichida ishlaydiAppComponent’ning barcha child component’larida ham ishlaydi- Lekin project’ning boshqa joylarida mavjud bo‘lmaydi
Bu usul ko‘proq lokal service’lar uchun ishlatiladi.
Angular’da Dependency Injection daraxt (tree) bo‘yicha ishlaydi. Angular dependency qidirishni har doim hozirgi component’dan boshlab, tepaga qarab olib boradi:
Hozirgi component → Parent → Parent’ning parent’i → RootU eng yaqin providers dan service’ni oladi.
Agar hech qayerdan topilmasa va service @Injectable({ providedIn: 'root' }) bilan e’lon qilingan bo‘lsa, Root injector’dan olib ishlatadi.
Bu Angular’ning default ishlash tartibi.
Get Ruzmatboy Jumaniyozov’s stories in your inbox
Join Medium for free to get updates from this writer.
Lekin biz bu qidirish jarayonini boshqarishimiz mumkin. Buning uchun Resolution modifiers ishlatiladi.
Resolution modifiers:
@Self() —Faqat shu component’ning o‘zidan qidir.
Bunda kod parent’ga chiqmaydi va child’ga ham o‘tmaydi, faqat hozirgi component’ni ko‘radi
constructor(@Self() private service: Service) {}Bu qachon kerak?
- Parent’dan tasodifan kelayotgan service’larni bloklash uchun
- Component faqat o‘zining local service’i bilan ishlashi shart bo‘lsa
- Qattiq (qat’iy) arxitektura qilishda
2. @SkipSelf() — Bu @Self() ning teskarisi. Hozirgi component’ni tashlab o‘t, parent’dan boshlab qidir.
constructor(@SkipSelf() private service: Service) {}Parent → Parent’ning parent’i → RootBu qachon kerak?
- Parent’dagi service muhim bo‘lsa
- Child’dagi service ko‘rinmasligi kerak bo‘lsa
- Meros (inheritance) ishlatilgan arxitekturalarda
3. @Optional() — Agar dependency topilmasa, error bermagin.
Oddiy holatda service topilmasa:
NullInjectorError: No provider for Servicechiqadi va app yiqiladi.
@Optional() bilan esa:
- Error chiqmaydi
service→nullbo‘ladi- App ishlashda davom etadi
constructor(@Optional() private service?: Service) {}Bu ko‘pincha boshqa modifierlar bilan birga ishlatiladi:
constructor(
@SkipSelf()
@Optional()
private service?: Service
) {}Yoki:
constructor(
@Self()
@Optional()
private service?: Service
) {}Provider strategies
Endi biz provider’ni qanday boshqarish mumkinligini ko‘ramiz. Angular’da providers orqali DI tizimini juda moslashuvchan qilib sozlash mumkin.
@Component({
selector: 'app-root',
template: '',
providers: [Service]
})Bu yerda providers meta-data orqali biz service qanday yaratilishini va qaysi qiymat qaytarilishini to‘liq boshqara olamiz. Buni esa provider strategies yordamida qilamiz.
1. useValue
DI so‘ralganda class yaratmasdan, biz bergan tayyor qiymatni qaytarsin.
Bu holatda bizda new Service() bo’lmaydi , Angular to’gridan-to’gri
{count: 100} ni beradi. useValue primitive qiymatlar, oddiy objectlarni qabul qiladi
2. useClass
Bitta service o‘rniga boshqa class’dan yangi instance yaratadi.
Bu yerda AppService so’ralsa , Angular new AppChildServiceni qaytib beradi yangi instance qaytaradi. mock data bilan ishlamoqchi bolsak yoki brin bir kutubxonani chaqirganda boshqa bir serviceni berish kerak bolsa ishlatamiz
3. useExisiting
Yangi instance yaratmay, bor bo‘lgan instance’ni boshqa nom bilan ishlatiladi.
Bu holatda faqat bitta instance yaratiladi AppService ham Service ham bir xil objectga ishora qiladi . Farqi useClass yangi instance yaratadi bunda mavjud instanceni qayta ishlatadi.
4. useFactory
Service qanday yaratilishini function orqali o‘zing belgilaymiz.








