IslomDevIslomDev
Booster
Imtihon
Booster
Imtihon
  • Angular Intervyu Tayyorgarlik
  • JavaScript / TypeScript

    • JavaScript / TypeScript
    • Asoslar (JavaScript)
    • Asinxronlik
    • Prototip va OOP
    • TypeScript
    • Performance
  • Algoritmlash

    • Algoritmlash
    • Murakkablik tahlili
    • Ma'lumot tuzilmalari
    • Qidiruv va Saralash
    • Algoritmik paradigmalar
    • Amaliy masalalar
  • Angular — Boshlang'ich

    • Angular — Boshlang'ich
    • Component
    • Template
    • Change Detection
    • Advanced Component
  • Angular — Service va DI

    • Angular — Service va DI
    • Service asoslari
    • HTTP
    • Hierarchical DI
    • Advanced DI
    • State management (service)
  • Angular — Versiyalar

    • Angular — Versiyalar
    • Angular 12–13
    • Angular 14
    • Angular 15
    • Angular 16
    • Angular 17
    • Angular 18+
  • Angular — Directive

    • Angular — Directive
    • Built-in Directives
    • Custom Attribute Directive
    • Custom Structural Directive
    • Advanced
  • Angular — RxJS

    • Angular — RxJS
    • Observable asoslari
    • Asosiy operatorlar
    • Higher-order operatorlar
    • Combination operatorlar
    • Subject turlari
    • Xato va xotira
    • Advanced
  • Angular — Pipe

    • Angular — Pipe
    • Built-in Pipes
    • Custom Pipe
    • Performance
  • Angular — Forms

    • Angular — Forms
    • Template-driven Forms
    • Reactive Forms
    • Validators
    • Advanced
  • Angular — NgModule

    • Angular — NgModule
    • NgModule asoslari
    • Module arxitekturasi
    • Lazy Loading
    • Standalone vs NgModule
  • Angular — Sintaksis va Clean Code

    • Angular — Sintaksis va Clean Code
    • Template sintaksisi
    • Angular 17+ yangi sintaksis
    • Komponent arxitekturasi
    • Performance pattern'lar
    • SOLID va Clean Code
    • Testing

Advanced DI

Daraja:

Angular DI faqat class'lardan iborat emas — InjectionToken, factory provider va multi provider kabi kengaytirilgan imkoniyatlar mavjud. Ilova ishga tushishdan oldin konfiguratsiya yuklash ham shu yerda.

InjectionToken — non-class dependency

Senior

Nima bu?

Ba'zi dependency'lar class emas — string, ob'ekt, funksiya yoki interface. TypeScript interface runtime'da yo'qoladi, shuning uchun InjectionTokenT`` yaratiladi. Token orqali DI tizimida aniq identifikatsiya qilinadi.

Ikkita klassik capqon: (1) provider ro'yxatga qo'shilmagan tokenni inject(TOKEN) bilan olishga urinsangiz, Angular NullInjectorError tashlaydi — oldini olish uchun inject(TOKEN, { optional: true }) yoki eski @Optional() ishlatiladi. (2) Har safar bootstrapApplication'da qo'lda provider yozish o'rniga, tokenni o'zi tree-shakable qilib e'lon qilish mumkin: new InjectionToken<AppConfig>('app.config', { providedIn: 'root', factory: () => defaultConfig }) — bu holda alohida providers yozish shart emas, token ishlatilmasa bundle'dan chiqib ketadi.

Kod misoli

import { InjectionToken, inject } from '@angular/core';

export interface AppConfig {
  apiUrl: string;
  featureFlags: Record<string, boolean>;
}

export const APP_CONFIG = new InjectionToken<AppConfig>('app.config');

// main.ts
bootstrapApplication(AppComponent, {
  providers: [
    {
      provide: APP_CONFIG,
      useValue: {
        apiUrl: 'https://api.example.com',
        featureFlags: { darkMode: true, betaSearch: false },
      },
    },
  ],
});

@Injectable({ providedIn: 'root' })
export class ApiService {
  private config = inject(APP_CONFIG);

  fetchUsers(): Observable<User[]> {
    return this.http.get<User[]>(`${this.config.apiUrl}/users`);
  }
}

Imtihonda

Savol: Nima uchun 'API_URL' as any o'rniga InjectionToken?

Javob: String token collision xavfi bor (turli modullar bir xil string). InjectionToken unique reference — tip xavfsizligi va tree-shaking uchun standart yondashuv.

Savol: Provider berilmagan tokenni inject() qilsangiz nima bo'ladi va qanday oldini olasiz?

Javob: NullInjectorError tashlanadi. inject(TOKEN, { optional: true }) bilan null qaytariladi, yoki tokenni factory bilan providedIn: 'root' qilib e'lon qilib default qiymat berasiz.

Yodlash uchun

Interface/config/primitive → `InjectionToken`T``. `inject(APP_CONFIG)` — tip bilan.

useClass, useValue, useFactory, useExisting

Senior

Nima bu?

Provider recipe turlari:

  • useClass — class instance yarat (default).
  • useValue — tayyor qiymat (ob'ekt, string).
  • useFactory — funksiya orqali dinamik yaratish (boshqa dependency kerak bo'lsa).
  • useExisting — boshqa token'ga alias (bir instance, ikki nom).

Kod misoli

abstract class Logger {
  abstract log(msg: string): void;
}

class ConsoleLogger implements Logger {
  log(msg: string): void { console.log(msg); }
}

class RemoteLogger implements Logger {
  log(msg: string): void { /* API ga yuborish */ }
}

const IS_PROD = new InjectionToken<boolean>('isProd');

bootstrapApplication(AppComponent, {
  providers: [
    // useValue
    { provide: IS_PROD, useValue: environment.production },

    // useClass — shartli
    {
      provide: Logger,
      useClass: environment.production ? RemoteLogger : ConsoleLogger,
    },

    // useFactory
    {
      provide: APP_CONFIG,
      useFactory: (isProd: boolean) => ({
        apiUrl: isProd ? 'https://api.prod.com' : 'http://localhost:3000',
      }),
      deps: [IS_PROD],
    },

    // useExisting — alias
    { provide: 'LegacyLogger', useExisting: Logger },
  ],
});

Imtihonda

Savol: useExisting va useClass farqi?

Javob: useClass — yangi instance yaratadi. useExisting — mavjud token'ning xuddi shu instance'iga ishora (alias, singleton saqlanadi).

Yodlash uchun

useValue — konstanta. useFactory — deps bilan dinamik. useExisting — alias. useClass — standart class.

multi: true provider

Senior

Nima bu?

Odatda bir token — bitta provider. multi: true bo'lsa, bir xil token uchun bir nechta provider ro'yxatga olinadi va inject qilganda array qaytariladi. Interceptor'lar, APP_INITIALIZER va plugin arxitektura uchun ishlatiladi.

Kod misoli

export const VALIDATORS = new InjectionToken<(value: string) => string | null>(
  'validators'
);

// Modul A
providers: [
  {
    provide: VALIDATORS,
    useValue: (v: string) => (v.length < 3 ? 'Kamida 3 belgi' : null),
    multi: true,
  },
]

// Modul B
providers: [
  {
    provide: VALIDATORS,
    useValue: (v: string) => (/[A-Z]/.test(v) ? null : 'Katta harf kerak'),
    multi: true,
  },
]

@Injectable({ providedIn: 'root' })
export class ValidationService {
  private validators = inject(VALIDATORS); // ValidatorFn[]

  validate(value: string): string | null {
    for (const fn of this.validators) {
      const error = fn(value);
      if (error) return error;
    }
    return null;
  }
}
// HTTP_INTERCEPTORS ham multi: true
{ provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true },
{ provide: HTTP_INTERCEPTORS, useClass: LoggingInterceptor, multi: true },

Imtihonda

Savol: multi: true bo'lmaganda ikkinchi provider nima qiladi?

Javob: Birinchisini ustiga yozadi (override). Faqat bitta provider qoladi — interceptor zanjiri buziladi.

Yodlash uchun

Bir token — ko'p implementatsiya → `multi: true` + `InjectionToken`T[]``.

APP_INITIALIZER — ilova ishga tushishdan oldin

Senior

Nima bu?

APP_INITIALIZER — ilova bootstrap qilinishidan oldin bajariladigan funksiyalar. Konfiguratsiya yuklash, auth token tekshirish, i18n fayllar olish uchun. Funksiya Promise yoki Observable qaytarsa, Angular kutadi.

Kod misoli

import { APP_INITIALIZER, inject } from '@angular/core';

@Injectable({ providedIn: 'root' })
export class ConfigLoaderService {
  private http = inject(HttpClient);
  config: AppConfig | null = null;

  load(): Promise<void> {
    return firstValueFrom(
      this.http.get<AppConfig>('/assets/config.json')
    ).then((cfg) => {
      this.config = cfg;
    });
  }
}

export function initializeApp(): () => Promise<void> {
  const loader = inject(ConfigLoaderService);
  return () => loader.load();
}

bootstrapApplication(AppComponent, {
  providers: [
    {
      provide: APP_INITIALIZER,
      useFactory: initializeApp,
      multi: true,
      deps: [], // inject() ishlatilgani uchun deps bo'sh
    },
  ],
});

Imtihonda

Savol: APP_INITIALIZER juda sekin bo'lsa nima bo'ladi?

Javob: Butun ilova osilib qoladi — foydalanuvchi blank screen ko'radi. Kritik bo'lmagan yuklashni component darajasiga ko'chirish yoki timeout qo'yish kerak.

Yodlash uchun

APP_INITIALIZER = bootstrap oldin, `multi: true`. Promise/Observable — Angular kutadi.

ENVIRONMENT_INITIALIZER (v14+)

Senior

Nima bu?

ENVIRONMENT_INITIALIZER — environment injector yaratilganda (bootstrap vaqtida) ishlaydigan funksiya. APP_INITIALIZER dan farqi: sinxron void qaytaradi, Promise kutmaydi. Global sozlash, third-party kutubxona init, telemetriya registratsiya uchun.

Kod misoli

import { ENVIRONMENT_INITIALIZER, inject } from '@angular/core';

export function setupAnalytics(): void {
  const router = inject(Router);
  router.events.pipe(
    filter((e): e is NavigationEnd => e instanceof NavigationEnd)
  ).subscribe((e) => {
    analytics.trackPageView(e.urlAfterRedirects);
  });
}

bootstrapApplication(AppComponent, {
  providers: [
    {
      provide: ENVIRONMENT_INITIALIZER,
      useValue: () => setupAnalytics(),
      multi: true,
    },
    {
      provide: ENVIRONMENT_INITIALIZER,
      useValue: () => {
        console.log('Environment ready:', new Date().toISOString());
      },
      multi: true,
    },
  ],
});

Imtihonda

Savol: APP_INITIALIZER vs ENVIRONMENT_INITIALIZER — qaysi biri async config uchun?

Javob: APP_INITIALIZER — Promise/Observable kutadi, config yuklash uchun. ENVIRONMENT_INITIALIZER — sinxron init (listener, global flag), bootstrap bloklamaydi.

Yodlash uchun

Async yuklash → APP_INITIALIZER. Sinxron setup (listener, log) → ENVIRONMENT_INITIALIZER.
Prev
Hierarchical DI
Next
State management (service)