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

Xato va xotira

Daraja:

Production Angular ilovasida xatolarni to'g'ri ushlash, retry strategiyasi va subscription'larni tozalash — barqarorlik va xotira sızıntısiz ishlash uchun majburiy.

catchError — xatoni ushlash

Middle

Nima bu?

catchError — stream ichidagi xatoni ushlab, fallback Observable qaytaradi yoki xatoni transform qiladi. HTTP 404/500, network xato va operator zanjirida stream'ni to'liq to'xtatmasdan davom ettirish uchun. throwError(() => err) bilan qayta throw yoki of(defaultValue) bilan default qiymat.

Kod misoli

import { catchError, of, throwError } from 'rxjs';

@Injectable({ providedIn: 'root' })
export class UserService {
  getUser(id: number) {
    return this.http.get<User>(`/api/users/${id}`).pipe(
      catchError((err: HttpErrorResponse) => {
        if (err.status === 404) {
          return of(null as User | null); // fallback
        }
        console.error('User fetch failed:', err.message);
        return throwError(() => new Error('Foydalanuvchi yuklanmadi'));
      })
    );
  }
}

// Global interceptor bilan birga
this.http.get('/api/data').pipe(
  catchError((err) => {
    this.errorService.report(err);
    return of([]); // UI bo'sh ro'yxat ko'rsatadi
  })
);

Imtihonda

  • catchError va subscribe ichidagi error callback farqi?
  • catchError ichida qayta throw qilish kerak bo'lsa nima qilinadi?

Yodlash uchun

catchError = zanjirda xato ushlash + fallback Observable qaytarish.

retry, retryWhen — qayta urinish

Middle

Nima bu?

retry(n) — xato bo'lganda avtomatik n marta qayta subscribe. retry({ count, delay }) — kechikish bilan. retryWhen — custom qayta urinish logikasi (exponential backoff). Vaqtinchalik network xatolari uchun; 401/404 kabi doimiy xatolarda retry foydasiz.

Gotcha: RxJS 7'dan boshlab retryWhen deprecated — endi retry({ delay: (error, retryCount) => timer(retryCount * 1000) }) orqali xuddi shu exponential backoff logikasi retry() ichida yoziladi, alohida retryWhen operatoriga ehtiyoj qolmagan. Yangi kodda retryWhen ko'rsangiz — bu legacy signal, refactor qilish kerak.

Kod misoli

import { retry, retryWhen, delayWhen, scan, take, tap } from 'rxjs/operators';
import { timer } from 'rxjs';

// Oddiy retry — 3 marta
this.http.get('/api/unstable').pipe(
  retry(3),
  catchError((err) => of(null))
);

// Delay bilan (RxJS 7+)
this.http.get('/api/data').pipe(
  retry({ count: 3, delay: 1000 })
);

// Exponential backoff — retryWhen (1s, 2s, 3s... kutish)
this.http.get('/api/data').pipe(
  retryWhen((errors) =>
    errors.pipe(
      tap((err) => console.log('Retry...', err.status)),
      scan((attempt) => attempt + 1, 0),
      delayWhen((attempt) => timer(attempt * 1000)),
      take(3)
    )
  )
);

Imtihonda

  • Qaysi HTTP status kodlarida retry mantiqiy?
  • retry va catchError tartibi muhimmi?

Yodlash uchun

Vaqtinchalik xato (503, network) → retry. Doimiy (401, 404) → catchError.

takeUntil — xotira sızdırmasi oldini olish

Middle

Nima bu?

takeUntil(notifier$) — notifier emit qilguncha stream'dan qiymat oladi, keyin avtomatik unsubscribe. Component destroy, modal yopilishi yoki bir nechta subscription'ni bitta destroy$ bilan tozalash uchun standart pattern.

Gotcha: takeUntil pipe zanjirida oxirgi operator bo'lishi kerak. Agar u switchMap/mergeMapdan oldin turib qolsa, tashqi stream to'xtaydi, lekin ichki (masalan, HTTP) Observable hali ham davom etadi va natija kelganda componentga urinib ko'radi — bu klassik "operator tartibi" xatosi va aynan shu sababli senior darajada tez-tez so'raladi.

Kod misoli

import { Component, OnDestroy } from '@angular/core';
import { Subject, interval } from 'rxjs';
import { takeUntil, switchMap } from 'rxjs/operators';

@Component({ /* ... */ })
export class LiveDataComponent implements OnDestroy {
  private destroy$ = new Subject<void>();

  ngOnInit() {
    interval(1000)
      .pipe(takeUntil(this.destroy$))
      .subscribe((n) => (this.tick = n));

    this.route.paramMap
      .pipe(
        takeUntil(this.destroy$),
        switchMap((p) => this.loadData(p.get('id')!))
      )
      .subscribe((data) => (this.data = data));
  }

  ngOnDestroy() {
    this.destroy$.next();
    this.destroy$.complete();
  }
}

Imtihonda

  • takeUntil va qo'lda unsubscribe afzalliklari?
  • destroy$ ni complete qilish kerakmi?

Yodlash uchun

destroy$ + takeUntil = barcha stream'lar bir joyda to'lanadi.

takeUntilDestroyed() — Angular 16+ avtomat

Middle

Nima bu?

takeUntilDestroyed() — Angular 16+ da DestroyRef bilan component/directive destroy bo'lganda avtomatik unsubscribe. ngOnDestroy va destroy$ Subject yozish shart emas. Constructor yoki injection context ichida chaqirilishi kerak.

Kod misoli

import { Component, DestroyRef, inject } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';

@Component({ /* ... */ })
export class ModernComponent {
  private destroyRef = inject(DestroyRef);
  private route = inject(ActivatedRoute);

  // Constructor injection context
  constructor() {
    interval(1000)
      .pipe(takeUntilDestroyed())
      .subscribe((n) => (this.count = n));
  }

  // Yoki destroyRef explicit
  ngOnInit() {
    this.route.paramMap
      .pipe(
        switchMap((p) => this.api.get(p.get('id')!)),
        takeUntilDestroyed(this.destroyRef)
      )
      .subscribe((data) => (this.data = data));
  }
}

Imtihonda

  • takeUntilDestroyed qayerda chaqiriladi?
  • Service ichida ishlatish mumkinmi?

Yodlash uchun

takeUntilDestroyed = destroy$ + ngOnDestroy o'rniga. Constructor/injection context.

Service root scope'da — destroy yo'q; takeUntilDestroyed faqat component/directive uchun.

async pipe — avtomat subscribe/unsubscribe

JuniorMiddle

Nima bu?

async pipe — template'da Observable yoki Promise'ni subscribe qiladi, qiymatni ko'rsatadi va component destroy'da avtomatik unsubscribe. Change detection bilan integratsiya. Manual subscribe, ngOnDestroy va memory leak xavfini kamaytiradi — zamonaviy Angular'da tavsiya etiladi.

Kod misoli

@Component({
  template: `
    @if (user$ | async; as user) {
      <h1>{{ user.name }}</h1>
      <p>{{ user.email }}</p>
    } @else {
      <p>Yuklanmoqda...</p>
    }

    @for (product of products$ | async; track product.id) {
      <app-product-card [product]="product" />
    }
  `,
})
export class ProfileComponent {
  user$ = this.http.get<User>('/api/me');
  products$ = this.productService.getAll();
}

Imtihonda

  • async pipe memory leak oldini oladimi?
  • Bir xil Observable template'da 3 marta | async — muammo bormi?

Yodlash uchun

async pipe = auto subscribe + unsubscribe. Bir nechta joyda — @let yoki as alias.

Angular 17+ `@if (data$ | async; as data)` — bitta subscribe, butun block'da data.

shareReplay(1) — bitta HTTP, ko'p subscriber

MiddleSenior

Nima bu?

shareReplay({ bufferSize: 1, refCount: true }) — cold Observable'ni multicast qiladi: birinchi subscriber HTTP ishga tushiradi, natija cache'lanadi, keyingi subscriber'lar cache'dan oladi. refCount: true — barcha subscriber ketganda subscription to'lanadi. Config, permissions, reference data uchun.

Gotcha: agar manba error qaytarsa, shareReplay xatoni ham cache'laydi — keyingi barcha subscriber'lar (hatto network tiklangandan keyin ham) xuddi shu eski xatoni qayta-qayta oladi, chunki manba qayta ishga tushmaydi. Bu — production'da "bir marta xato bo'lsa, butun ilova abadiy shu xatoni ko'rsatadi" degan real bug manbai; yechim — catchError bilan xatoni tutib fallback qaytarish yoki stream'ni qayta yaratish logikasi.

Kod misoli

@Injectable({ providedIn: 'root' })
export class AppConfigService {
  private config$ = this.http.get<AppConfig>('/api/config').pipe(
    shareReplay({ bufferSize: 1, refCount: true })
  );

  getConfig() {
    return this.config$;
  }
}

// 3 ta component subscribe — 1 ta HTTP
@Component({ /* A */ })
class HeaderComponent {
  config$ = inject(AppConfigService).getConfig();
}

@Component({ /* B */ })
class FooterComponent {
  config$ = inject(AppConfigService).getConfig();
}

Imtihonda

  • shareReplay(1) va BehaviorSubject farqi?
  • refCount: false bo'lsa nima bo'ladi?

Yodlash uchun

shareReplay(1) = HTTP cache + hot multicast. refCount: true = tozalash.

refCount: false — root service'da doimiy cache; refCount: true — keraksiz bo'lganda tozalash.
Prev
Subject turlari
Next
Advanced