Sobes.tech
Middle+

Jak działa pętla zdarzeń (event loop) w API web?

sobes.tech AI

Odpowiedź od AI

Pętla zdarzeń w JavaScript (w kontekście przeglądarki internetowej) to mechanizm umożliwiający wykonywanie operacji asynchronicznych bez blokowania głównego wątku wykonawczego. Składa się z kilku komponentów:

  • Heap (Stos): Obszar pamięci, w którym przechowywane są obiekty.
  • Call Stack (Stos wywołań): Struktura danych LIFO, śledząca wykonywanie funkcji synchronicznych.
  • Web APIs: Dostarczane przez przeglądarkę (DOM, AJAX, setTimeout, setInterval, Event Listeners itp.). Nie są częścią silnika JavaScript.
  • Callback Queue (Kolejka callback): / Task Queue (Kolejka zadań): Kolejka wiadomości do wykonywania operacji asynchronicznych.
  • Microtask Queue (Kolejka mikro-zadań): Priorytetowa kolejka dla mikro-zadań (Promise.then(), async/await, queueMicrotask). Wykonywana przed kolejką zadań.
  • Event Loop (Pętla zdarzeń): Nieustannie sprawdza stos wywołań i kolejkę. Jeśli stos jest pusty, przenosi pierwszy obsługiwacz z kolejki mikro-zadań na stos. Po opróżnieniu kolejki mikro-zadań, przenosi pierwszy obsługiwacz z kolejki zadań na stos.

Proces działa następująco:

  1. Kod synchroniczny jest wykonywany, a funkcje umieszczane na stosie wywołań.
  2. Gdy napotkamy operację asynchroniczną (np. setTimeout), jest ona przekazywana do odpowiedniego Web API. Wykonanie kodu synchronicznego kontynuuje się.
  3. Web API wykonuje operację w tle.
  4. Po zakończeniu operacji asynchronicznej, obsługiwacz (callback) tej operacji jest umieszczany w kolejce zadań (dla zwykłych operacji async) lub kolejce mikro-zadań (dla promes).
  5. Pętla zdarzeń nieustannie sprawdza stos wywołań. Jeśli jest pusty:
    • Sprawdza kolejkę mikro-zadań. Jeśli są obsługiwacze, przenosi je do stosu wywołań do wykonania, aż kolejka mikro-zadań będzie pusta.
    • Następnie sprawdza kolejkę zadań. Jeśli są obsługiwacze, przenosi pierwszy do stosu wywołań do wykonania.
  6. Proces ten powtarza się, umożliwiając wykonywanie operacji asynchronicznych bez blokowania głównego wątku.

Przykład z setTimeout:

// Kod wykonywany na stosie wywołań
console.log('Start');

// setTimeout - Web API. Callback umieszczany w kolejce zadań po 0ms.
// Rzeczywiste wykonanie może być opóźnione przez pętlę zdarzeń.
setTimeout(() => {
  console.log('Timeout');
}, 0);

// Kod wykonywany na stosie wywołań po setTimeout
console.log('Koniec');

// Wynik:
// Start
// Koniec
// Timeout

Przykład z promesami:

// Wykonywany na stosie wywołań
console.log('A');

// Promesa. Callback then() umieszczany w kolejce mikro-zadań
Promise.resolve().then(() => {
  console.log('B');
});

// Wykonywany na stosie wywołań
console.log('C');

// Wynik:
// A
// C
// B