Model izvršavanja JavaScripta je nijansiran i lako ga je pogrešno razumjeti. Učenje o petlji događaja u njezinoj srži može pomoći.

JavaScript je jezik s jednom niti, izgrađen za obavljanje zadataka jedan po jedan. Međutim, petlja događaja omogućuje JavaScriptu asinkrono rukovanje događajima i povratnim pozivima oponašanjem simultanih sustava programiranja. To osigurava izvedbu vaših JavaScript aplikacija.

Što je JavaScript petlja događaja?

JavaScriptova petlja događaja je mehanizam koji radi u pozadini svake JavaScript aplikacije. Omogućuje JavaScriptu da rukuje zadacima u nizu bez blokiranja njegove glavne izvršne niti. Ovo se naziva asinkrono programiranje.

Petlja događaja čuva red zadataka za pokretanje i hrani te zadatke s desne strane web API za izvršenje jedan po jedan. JavaScript prati te zadatke i obrađuje svaki prema razini složenosti zadatka.

Razumjeti potrebu za JavaScript petljom događaja i asinkronim programiranjem. Morate razumjeti koji problem to u biti rješava.

Uzmite ovaj kod, na primjer:

instagram viewer
functionlongRunningFunction() {
// This function does something that takes a long time to execute.
for (var i = 0; i < 100000; i++) {
console.log("Hello")
}
}

functionshortRunningFunction(a) {
return a * 2 ;
}

functionmain() {
var startTime = Date.now();
longRunningFunction();

var endTime = Date.now();

// Prints the amount of time it took to execute functions
console.log(shortRunningFunction(2));
console.log("Time taken: " + (endTime - startTime) + " milliseconds");
}

main();

Ovaj kod prvo definira funkciju tzv dugafunkcija(). Ova će funkcija obaviti neku vrstu složenog zadatka koji zahtijeva puno vremena. U ovom slučaju izvodi a za petlja koja se ponavlja preko 100 000 puta. Ovo znači to console.log("Zdravo") radi 100 000 puta.

Ovisno o brzini računala, to može potrajati dugo i blokirati se shortRunningFunction() od trenutnog izvršenja do završetka prethodne funkcije.

Za kontekst, ovdje je usporedba vremena potrebnog za pokretanje obje funkcije:

A onda singl shortRunningFunction():

Razlika između operacije od 2351 milisekunde i operacije od 0 milisekundi očita je kada ciljate izraditi učinkovitu aplikaciju.

Kako petlja događaja pomaže u izvedbi aplikacije

Petlja događaja ima različite faze i dijelove koji pridonose funkcioniranju sustava.

Skup poziva

JavaScript stog poziva bitan je za način na koji JavaScript obrađuje pozive funkcija i događaja iz vaše aplikacije. JavaScript kod se kompilira od vrha prema dolje. Međutim, Node.js, nakon čitanja koda, Node.js će dodijeliti pozive funkcija od dna prema vrhu. Dok čita, gura definirane funkcije kao okvire u pozivni stog jednu po jednu.

Stog poziva odgovoran je za održavanje konteksta izvršenja i ispravnog redoslijeda funkcija. To čini radeći kao zadnji-ušao-prvi-izišao (LIFO) stog.

To znači da će zadnji okvir funkcije koji vaš program gurne na stog poziva biti prvi koji će iskočiti sa stoga i pokrenuti se. Ovo će osigurati da JavaScript održava pravi redoslijed izvršavanja funkcija.

JavaScript će izbaciti svaki okvir sa stoga dok ne bude prazan, što znači da su sve funkcije završile s radom.

Libuv Web API

Srž JavaScriptovih asinkronih programa je libuv. Biblioteka libuv napisana je u programskom jeziku C, koji može komunicirati s operativnim sustavom API-ji niske razine. Knjižnica će pružiti nekoliko API-ja koji omogućuju paralelno pokretanje JavaScript koda s drugim kodirati. API-ji za stvaranje niti, API za komunikaciju između niti i API za upravljanje sinkronizacijom niti.

Na primjer, kada koristite setTimeout u Node.js za pauziranje izvršenja. Mjerač vremena se postavlja putem libuva, koji upravlja petljom događaja za izvršavanje funkcije povratnog poziva nakon što prođe navedena odgoda.

Slično, kada mrežne operacije izvodite asinkrono, libuv rukuje tim operacijama u neblokirajućem način, osiguravajući da drugi zadaci mogu nastaviti s obradom bez čekanja da se operacija ulaza/izlaza (I/O) kraj.

Red povratnih poziva i događaja

Red povratnih poziva i događaja je mjesto gdje funkcije povratnih poziva čekaju na izvršenje. Kada asinkrona operacija završi iz libuva, odgovarajuća funkcija povratnog poziva dodaje se u ovaj red čekanja.

Evo kako ide slijed:

  1. JavaScript premješta asinkrone zadatke u libuv kako bi ih on obradio i odmah nastavlja rukovati sljedećim zadatkom.
  2. Kada asinkroni zadatak završi, JavaScript dodaje svoju funkciju povratnog poziva u red čekanja za povratni poziv.
  3. JavaScript nastavlja izvršavati druge zadatke u nizu poziva dok ne završi sa svime u trenutnom redoslijedu.
  4. Nakon što se stog poziva isprazni, JavaScript pregledava red povratnih poziva.
  5. Ako postoji povratni poziv u redu čekanja, on gura prvi na stog poziva i izvršava ga.

Na taj način asinkroni zadaci ne blokiraju glavnu nit, a red povratnih poziva osigurava da se njihovi odgovarajući povratni pozivi izvrše redoslijedom kojim su dovršeni.

Ciklus petlje događaja

Petlja događaja također ima nešto što se zove red čekanja mikrozadataka. Ovaj posebni red čekanja u petlji događaja sadrži mikrozadatke koji su planirani za izvršenje čim završi trenutni zadatak u stogu poziva. Ovo se izvršenje događa prije sljedećeg iscrtavanja ili iteracije petlje događaja. Mikrozadaci su zadaci visokog prioriteta s prednošću nad uobičajenim zadacima u petlji događaja.

Mikrozadatak se obično stvara kada se radi s Promises. Kad god obećanje riješi ili odbije, to odgovara .zatim() ili .ulov() callbacks pridružuje se redu čekanja mikrozadataka. Mogli biste koristiti taj red čekanja za upravljanje zadacima koje je potrebno odmah izvršiti nakon trenutne operacije, kao što je ažuriranje korisničkog sučelja vaše aplikacije ili rukovanje promjenama stanja.

Na primjer, web aplikacija koja izvodi dohvaćanje podataka i ažurira korisničko sučelje na temelju dohvaćenih podataka. Korisnici mogu pokrenuti ovo dohvaćanje podataka uzastopnim pritiskom na gumb. Svaki klik na gumb pokreće asinkronu operaciju dohvaćanja podataka.

Bez mikrozadataka, petlja događaja za ovaj zadatak radila bi na sljedeći način:

  1. Korisnik više puta klikne gumb.
  2. Svaki klik na gumb pokreće asinkronu operaciju dohvaćanja podataka.
  3. Kako operacije dohvaćanja podataka dovrše, JavaScript dodaje njihove odgovarajuće povratne pozive u uobičajeni red čekanja zadataka.
  4. Petlja događaja započinje obradu zadataka u redovnom redu čekanja zadataka.
  5. Ažuriranje korisničkog sučelja temeljeno na rezultatima dohvaćanja podataka izvršava se čim redovni zadaci to dopuste.

Međutim, s mikrozadacima, petlja događaja radi drugačije:

  1. Korisnik više puta klikne gumb i pokreće asinkronu operaciju dohvaćanja podataka.
  2. Kako se operacije dohvaćanja podataka završe, petlja događaja dodaje njihove odgovarajuće povratne pozive u red čekanja mikrozadataka.
  3. Petlja događaja počinje s obradom zadataka u redu čekanja mikrozadataka odmah nakon dovršetka trenutnog zadatka (klik na gumb).
  4. Ažuriranje korisničkog sučelja na temelju rezultata dohvaćanja podataka izvršava se prije sljedećeg redovnog zadatka, pružajući bolje korisničko iskustvo.

Evo primjera koda:

const fetchData = () => {
returnnewPromise(resolve => {
setTimeout(() => resolve('Data from fetch'), 2000);
});
};

document.getElementById('fetch-button').addEventListener('click', () => {
fetchData().then(data => {
// This UI update will run before the next rendering cycle
updateUI(data);
});
});

U ovom primjeru svaki klik na gumb "Dohvati" poziva dohvatiPodatke(). Svaka operacija dohvaćanja podataka planira se kao mikrozadatak. Na temelju dohvaćenih podataka, ažuriranje korisničkog sučelja izvršava se odmah nakon završetka svake operacije dohvaćanja, prije svih drugih zadataka iscrtavanja ili petlje događaja.

Ovo osigurava da korisnici vide ažurirane podatke bez kašnjenja zbog drugih zadataka u petlji događaja.

Korištenje mikrozadataka u ovakvim scenarijima može spriječiti smetnje korisničkog sučelja i omogućiti brže i glađe interakcije u vašoj aplikaciji.

Implikacije petlje događaja za web razvoj

Razumijevanje petlje događaja i načina korištenja njegovih značajki bitno je za izgradnju učinkovitih i responzivnih aplikacija. Petlja događaja pruža asinkrone i paralelne mogućnosti, tako da možete učinkovito rješavati složene zadatke u svojoj aplikaciji bez ugrožavanja korisničkog iskustva.

Node.js pruža sve što vam je potrebno, uključujući web radnike za postizanje daljnjeg paralelizma izvan glavne niti JavaScripta.