Event Loop u JavaScript-u

Jose Vela's Avatar
Jose Vela
CTO Comiral
4. мај 2024.

Event Loop u JavaScript-u

Da li ste se ikada zapitali kako funkcioniše proces izvršavanja koda u JavaScript-u? Kako jezik upravlja prioritetom između različitih blokova ili rukuje asinhronim pozivima iako je "single-threaded" (jednonitni) jezik?

Ključni mehanizam koji upravlja ovim ponašanjem je Event Loop u JavaScript-u.

Da biste razumeli njegov rad, neophodno je da se upoznate sa različitim komponentama unutar JavaScript okruženja za izvršavanje.

Komponente JavaScript okruženja za izvršavanje

JavaScript motor (Engine)

Pošto pregledač ne može direktno da obradi JavaScript datoteke, u igru ulazi JavaScript motor. On je osnova rada jezika i sastoji se od hipa (heap) i steka poziva (call stack).

Hip (Heap)

Hip je mesto gde se podaci čuvaju u memoriji. Iako njegovo upravljanje može biti složeno, radi lakšeg objašnjenja, fokusiraćemo se na druge aspekte.

Stek poziva (Call Stack)

Call Stack je mesto gde se slažu pozivi za izvršavanje našeg koda. Međutim, šta se dešava ako izvršavanje neke operacije traje predugo? Da li će se ostale zaustaviti? Da bi izbegao ovaj problem, JavaScript delegira ove zadatke Web API-jima.

Web API-ji

Prilikom razvoja za veb, susrećemo se sa različitim Web API-jima koji komuniciraju sa pregledačem kako bi rešili zadatke koji mogu potrajati, čineći ih asinhronim. Ovi zadaci se završavaju i vraćaju u obliku povratnih poziva (callbacks) ili obećanja (promises).

Neki od najčešćih Web API-ja su: fetch, setTimeout, DOM, localStorage, sessionStorage, HTMLDivElement, document, URL, XMLHttpRequest.

Red zadataka (Task Queue)

Pozivi Web API-jima koji vraćaju rezultate u obliku povratnih poziva (callbacks) ređaju se u red zadataka. To uključuje interakcije sa DOM-om, HTTP zahteve, tajmere, između ostalog.

Razmotrite sledeći blok koda kao primer:

console.log("Početak primera");

setTimeout(() => {
	console.log("Čekanje dve sekunde");
}, 2000);

console.log("Kraj primera");
  • Početak primera
  • Kraj primera
  • Čekanje dve sekunde

Prilikom izvršavanja ovog koda, console.log naredbe se šalju direktno u Call Stack i izvršavaju, što rezultira sledećim redosledom:

  1. "SPočetak primera"
  2. "Kraj primera"

Funkcija setTimeout, sa odlaganjem od 2 sekunde, obrađuje se preko Web API-ja. Kada se završi, šalje se u red zadataka na izvršavanje.

Red mikrozadataka (Microtask Queue)

bećanja (promises), kada se razreše, šalju svoje rukovaoce (.then, .catch ili .finally) u red mikrozadataka. Ovi rukovaoci se izvršavaju asinhrono, čak i ako se obećanje razreši odmah. Mikrozadaci imaju prioritet nad zadacima u redu zadataka.

Na primer:

let promise = Promise.resolve();

promise.then(() => alert("Obećanje razrešeno"));

alert("Kod završen"); // Ovo se izvršava prvo

Event Loop

Event Loop je fundamentalni mehanizam u JavaScript-u koji osigurava da se asinhroni kod obrađuje efikasno. On radi neprekidno, nadgledajući Call Stack i redove zadataka (Task Queue) i mikrozadataka (Microtask Queue).

Kada JavaScript motor naiđe na asinhroni zadatak, kao što je poziv setTimeout ili mrežna operacija, on delegira taj zadatak Web API-jima pregledača. U međuvremenu, JavaScript kod nastavlja da se izvršava u Call Stack-u. Kada se asinhroni zadatak završi, on se smešta u Task Queue.

Ovde na scenu stupa Event Loop: njegova glavna funkcija je da proveri da li je Call Stack prazan. Ako jeste, uzima prvi zadatak iz Task Queue-a i postavlja ga u Call Stack na izvršavanje. To znači da asinhroni zadaci čekaju svoj red u redu dok Call Stack ne postane slobodan.

Međutim, postoji važan detalj: mikrozadaci. Oni imaju prioritet nad običnim zadacima u redu zadataka. Kada se Call Stack isprazni, Event Loop prvo uzima sve mikrozadatke iz Microtask Queue-a i izvršava ih redom, pre nego što se vrati običnim zadacima u Task Queue-u.

Ovo ponašanje je ključno kako bi se osiguralo da se obećanja i njihovi rukovaoci .then, .catch i .finally izvršavaju blagovremeno i predvidivo, čak i u situacijama gde se asinhroni i sinhroni kod prepliću.

Ukratko, Event Loop u JavaScript-u garantuje uredan i efikasan tok izvršavanja, dajući prioritet mikrozadacima pre običnih zadataka, i osiguravajući da se asinhroni kod ispravno obrađuje unutar konteksta jedne niti izvršavanja. Ova struktura je od suštinskog značaja za razvoj modernih veb aplikacija i sigurno i efikasno upravljanje asinhronim operacijama.

Related stories

Bare Metal is Essential for Critical Privacy

2 Feb

Bare Metal is Essential for Critical Privacy

For critical communications—encrypted messaging, patient records, or legal transcripts — cyber threats and increasingly strict data regulations are a risk and an ethical deal-breaker.

The "Noisy Neighbor" Cure

4 Jan

The "Noisy Neighbor" Cure

When one of those "neighbors" has a spike in traffic or runs a massive data-processing job, your application pays the price. This is where Bare Metal Servers step in as the ultimate cure.

Heap and memory management in JavaScript

5 May

Heap and memory management in JavaScript

Memory management varies significantly between different programming languages. In high-level languages like JavaScript, Python, or C#, memory management is automatic.