Service asoslari
Service — Angular'da @Injectable dekorator bilan belgilanadigan class bo'lib, component'lardan mustaqil biznes logika, API chaqiruvlari va umumiy holatni boshqarish uchun ishlatiladi.
@Injectable() dekoratori
Nima bu?
@Injectable() Angular DI tizimiga class DI konteyneriga qo'shilishini bildiradi. Service class'ida bu dekorator majburiy — aks holda Angular dependency'larni inject qila olmaydi. Service ichida boshqa service inject qilinsa, @Injectable({ providedIn: 'root' }) yoki providers array orqali ro'yxatdan o'tkazish kerak.
Kod misoli
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root',
})
export class UserService {
private users: string[] = ['Ali', 'Vali'];
getUsers(): string[] {
return [...this.users];
}
addUser(name: string): void {
this.users.push(name);
}
}
// Component'da ishlatish
@Component({
selector: 'app-user-list',
standalone: true,
template: `<ul><li *ngFor="let u of users">{{ u }}</li></ul>`,
})
export class UserListComponent {
users: string[];
constructor(private userService: UserService) {
this.users = this.userService.getUsers();
}
}
Imtihonda
Savol: @Injectable() dekoratorisiz service yaratib bo'ladimi? Nima bo'ladi?
Javob: Class yaratish mumkin, lekin Angular DI uni tan olmaydi. Constructor injection ishlamaydi, inject(UserService) ham xato beradi — service provider ro'yxatida bo'lmaydi.
Yodlash uchun
providedIn: 'root' — singleton service
Nima bu?
providedIn: 'root' service'ni butun ilova bo'ylab bitta instance (singleton) qilib ro'yxatdan o'tkazadi. Root injector'da yaratiladi — har qanday component bir xil instance oladi. Tree-shaking ham ishlaydi: hech qayerda inject qilinmasa, bundle'dan chiqariladi.
Kod misoli
@Injectable({ providedIn: 'root' })
export class CartService {
private items: { id: number; qty: number }[] = [];
addItem(id: number): void {
const existing = this.items.find((i) => i.id === id);
existing ? existing.qty++ : this.items.push({ id, qty: 1 });
}
totalItems(): number {
return this.items.reduce((sum, i) => sum + i.qty, 0);
}
}
// Ikki component bir xil CartService instance'ini oladi
@Component({ selector: 'app-header', template: `Savat: {{ cart.totalItems() }}` })
export class HeaderComponent {
constructor(public cart: CartService) {}
}
@Component({ selector: 'app-product', template: `<button (click)="cart.addItem(1)">Qo'shish</button>` })
export class ProductComponent {
constructor(public cart: CartService) {}
}
Imtihonda
Savol: providedIn: 'root' bilan providers: [CartService] (component darajasida) farqi nima?
Javob: root — butun ilovada 1 ta instance. Component providers — har bir component uchun alohida instance (component va uning bolalari uchun).
Yodlash uchun
providedIn: 'any' / 'platform' — farqlari
Nima bu?
providedIn: 'root'— bitta global singleton (root injector).providedIn: 'platform'— platform darajasida singleton. SSR'da server va browser alohida platform injector'ga ega; bir xil platform ichida bitta instance.providedIn: 'any'— har bir lazy-loaded module uchun alohida instance, lekin eager modullar root bilan baham ko'radi. Kam ishlatiladi; modul izolyatsiyasi kerak bo'lganda foydali.
Kod misoli
// Platform — SSR server/client alohida
@Injectable({ providedIn: 'platform' })
export class PlatformLoggerService {
log(msg: string): void {
console.log(`[${typeof window === 'undefined' ? 'SERVER' : 'BROWSER'}]`, msg);
}
}
// Any — lazy modul boshiga alohida instance
@Injectable({ providedIn: 'any' })
export class FeatureStateService {
private state = new Map<string, unknown>();
set(key: string, value: unknown): void {
this.state.set(key, value);
}
}
Imtihonda
Savol: Qachon platform, qachon any ishlatiladi?
Javob: platform — SSR yoki micro-frontend platformalarida platform-scope singleton kerak bo'lganda. any — lazy modul ichida boshqa modul bilan state aralashmasin, lekin root bilan ham baham ko'rish kerak bo'lganda (kam holat).
Yodlash uchun
inject() funksiya (v14+) — constructor'siz
Nima bu?
Angular 14+ da inject() funksiyasi DI konteyneridan dependency olish uchun ishlatiladi. Constructor injection o'rniga class field, factory function yoki functional guard/interceptor ichida qulay. inject() faqat injection context ichida chaqiriladi (constructor, field initializer, factory, route guard va h.k.).
Nozik joyi: injection context faqat sinxron chaqiruv stack'i davomida amal qiladi. Konstruktor ichida setTimeout(() => inject(Foo), 0) yoki .then(() => inject(Foo)) kabi asinxron callback ichida chaqirish ham xato beradi — chunki callback bajarilganda context allaqachon yopilgan bo'ladi. Bunday holatlarda kerakli service'ni oldindan (sinxron qismda) inject() bilan o'zgaruvchiga saqlab, keyin callback ichida o'sha o'zgaruvchidan foydalanish kerak.
Kod misoli
import { Component, inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
@Component({
selector: 'app-users',
standalone: true,
template: `@for (u of users(); track u.id) { <p>{{ u.name }}</p> }`,
})
export class UsersComponent {
private http = inject(HttpClient);
users = signal<User[]>([]);
ngOnInit(): void {
this.http.get<User[]>('/api/users').subscribe((data) => this.users.set(data));
}
}
// Functional interceptor ichida
export const authInterceptor: HttpInterceptorFn = (req, next) => {
const token = inject(AuthService).getToken();
return next(req.clone({ setHeaders: { Authorization: `Bearer ${token}` } }));
};
Imtihonda
Savol: inject() ni ngOnInit ichida chaqirish mumkinmi?
Javob: Yo'q. ngOnInit injection context emas. inject() faqat construction vaqtida (field initializer, constructor) yoki boshqa injection context'da ishlaydi.
Yodlash uchun
