A JavaScript végrehajtási modellje árnyalt és könnyen félreérthető. Az eseményhurok lényegének megismerése segíthet.

A JavaScript egy egyszálú nyelv, amely a feladatok egyenkénti kezelésére készült. Az eseményhurok azonban lehetővé teszi, hogy a JavaScript aszinkron módon kezelje az eseményeket és a visszahívásokat az egyidejű programozási rendszerek emulálásával. Ez biztosítja a JavaScript-alkalmazások teljesítményét.

Mi az a JavaScript eseményhurok?

A JavaScript eseményhurka egy olyan mechanizmus, amely minden JavaScript-alkalmazás hátterében fut. Lehetővé teszi a JavaScript számára, hogy sorrendben kezelje a feladatokat anélkül, hogy blokkolná a fő végrehajtási szálat. Ezt úgy nevezik aszinkron programozás.

Az eseményhurok sorban tartja a futtatandó feladatokat, és ezeket a feladatokat a jobb oldalon táplálja web API a végrehajtáshoz egyenként. A JavaScript nyomon követi ezeket a feladatokat, és mindegyiket a feladat összetettségi szintjének megfelelően kezeli.

A JavaScript eseményhurok és az aszinkron programozás szükségességének megértése. Meg kell értened, hogy lényegében milyen problémát old meg.

instagram viewer

Vegyük például ezt a kódot:

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();

Ez a kód először definiál egy ún longRunningFunction(). Ez a funkció valamilyen összetett, időigényes feladatot hajt végre. Ebben az esetben végrehajtja a számára ciklus iterációja több mint 100 000 alkalommal. Ez azt jelenti console.log("Hello") 100 000-szer fut át.

A számítógép sebességétől függően ez hosszú ideig tarthat, és leállhat shortRunningFunction() az azonnali végrehajtástól az előző funkció befejezéséig.

A szövegkörnyezet szempontjából íme a két függvény futtatásához szükséges idő összehasonlítása:

És akkor a szingli shortRunningFunction():

A 2351 ezredmásodperces és a 0 ezredmásodperces művelet közötti különbség nyilvánvaló, ha egy hatékony alkalmazást szeretne készíteni.

Hogyan segíti az eseményhurok az alkalmazások teljesítményét

Az eseményhuroknak különböző szakaszai és részei vannak, amelyek hozzájárulnak a rendszer működéséhez.

A Call Stack

A JavaScript-hívási verem elengedhetetlen ahhoz, hogy a JavaScript hogyan kezeli az alkalmazás függvény- és eseményhívásait. A JavaScript kód felülről lefelé fordítódik. A Node.js azonban a kód beolvasásakor a Node.js függvényhívásokat rendel hozzá alulról felfelé. Olvasás közben a definiált függvényeket keretként egyenként tolja be a hívási verembe.

A hívási verem felelős a végrehajtási környezet és a funkciók helyes sorrendjének fenntartásáért. Ezt úgy éri el, hogy Last-In-First-Out (LIFO) veremként működik.

Ez azt jelenti, hogy a program által a hívási verembe utoljára helyezett függvénykeret lesz az első, amely kiugrik a veremből és fut. Ez biztosítja, hogy a JavaScript fenntartsa a függvényvégrehajtás megfelelő sorrendjét.

A JavaScript minden egyes keretet kiugrik a veremből, amíg ki nem ürül, ami azt jelenti, hogy az összes funkció be nem fut.

Libuv Web API

A JavaScript aszinkron programjainak magja az libuv. A libuv könyvtár C programozási nyelven íródott, amely kölcsönhatásba léphet az operációs rendszerrel alacsony szintű API-k. A könyvtár számos API-t biztosít, amelyek lehetővé teszik a JavaScript kód párhuzamos futtatását másokkal kód. API-k szálak létrehozásához, API a szálak közötti kommunikációhoz és API a szálak szinkronizálásának kezelésére.

Például amikor használod setTimeout a Node.js-ben a végrehajtás szüneteltetéséhez. Az időzítőt a libuven keresztül állítják be, amely az eseményhurkot kezeli a visszahívási funkció végrehajtásához, miután a megadott késleltetés lejárt.

Hasonlóképpen, ha aszinkron módon hajt végre hálózati műveleteket, a libuv ezeket a műveleteket nem blokkoló módon kezeli. módon, biztosítva, hogy más feladatok folytathassák a feldolgozást anélkül, hogy megvárnák az input/output (I/O) műveletet vége.

A visszahívási és eseménysor

A visszahívási és eseménysor az, ahol a visszahívási függvények végrehajtásra várnak. Amikor egy aszinkron művelet befejeződik a libuv-ból, a megfelelő visszahívási függvény hozzáadódik ehhez a sorhoz.

Így megy a sorrend:

  1. A JavaScript áthelyezi az aszinkron feladatokat a libuv-ba, hogy az kezelje, és azonnal folytatja a következő feladat kezelését.
  2. Amikor az aszinkron feladat befejeződik, a JavaScript hozzáadja a visszahívási funkcióját a visszahívási sorhoz.
  3. A JavaScript addig hajtja végre a többi feladatot a hívási veremben, amíg minden az aktuális sorrendben el nem végez.
  4. Ha a hívási verem üres, a JavaScript megnézi a visszahívási sort.
  5. Ha van visszahívás a sorban, akkor az elsőt a hívásverembe tolja, és végrehajtja.

Ily módon az aszinkron feladatok nem blokkolják a főszálat, és a visszahívási sor biztosítja, hogy a megfelelő visszahívások a befejezésük sorrendjében fussanak le.

Az eseményhurok ciklus

Az eseményhuroknak is van valami, az úgynevezett mikrofeladat-sor. Ez a speciális sor az eseményhurokban tartalmazza a végrehajtásra ütemezett mikrofeladatokat, amint az aktuális feladat a hívási veremben befejeződik. Ez a végrehajtás a következő renderelés vagy eseményhurok iterációja előtt történik. A mikrofeladatok olyan magas prioritású feladatok, amelyek elsőbbséget élveznek az eseményhurok szokásos feladataival szemben.

A mikrofeladat általában akkor jön létre, amikor a Promises programmal dolgozik. Amikor egy Ígéret megoldja vagy elutasítja, annak megfelel .akkor() vagy .fogás() visszahívások csatlakoznak a mikrofeladat-sorhoz. Ezt a sort használhatja az aktuális művelet után azonnali végrehajtásra szoruló feladatok kezelésére, például az alkalmazás felhasználói felületének frissítésére vagy az állapotváltozások kezelésére.

Például egy webalkalmazás, amely adatlekérést hajt végre, és frissíti a felhasználói felületet a letöltött adatok alapján. A felhasználók egy gombra többszöri kattintással aktiválhatják ezt az adatlekérést. Minden gombnyomás aszinkron adatlekérési műveletet indít el.

Mikrofeladatok nélkül az eseményhurok ehhez a feladathoz a következőképpen működne:

  1. A felhasználó többször rákattint a gombra.
  2. Minden egyes gombkattintás aszinkron adatlekérési műveletet indít el.
  3. Amint az adatlekérési műveletek befejeződnek, a JavaScript hozzáadja a megfelelő visszahívásokat a szokásos feladatsorhoz.
  4. Az eseményhurok megkezdi a feladatok feldolgozását a normál feladatsorban.
  5. Az adatlekérési eredményeken alapuló felhasználói felület frissítése azonnal végrehajtódik, amint azt a szokásos feladatok lehetővé teszik.

A mikrofeladatok esetében azonban az eseményhurok másképp működik:

  1. A felhasználó többször rákattint a gombra, és elindít egy aszinkron adatlekérési műveletet.
  2. Amint az adatlekérési műveletek befejeződnek, az eseményhurok hozzáadja a megfelelő visszahívásokat a mikrofeladat-sorhoz.
  3. Az eseményhurok azonnal megkezdi a feladatok feldolgozását a mikrofeladatsorban az aktuális feladat befejezése után (gombkattintás).
  4. Az adatlekérés eredményein alapuló felhasználói felület-frissítés a következő szokásos feladat előtt fut le, így jobban reagál a felhasználói élményre.

Íme egy kódpélda:

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);
});
});

Ebben a példában a „Fetch” gombra való kattintás minden egyes alkalommal hív fetchData(). Minden adatlekérési művelet ütemezése mikrofeladatként működik. A lekért adatok alapján a felhasználói felület frissítése minden lekérés befejezése után azonnal végrehajtódik, minden más renderelési vagy eseményhurkos feladat előtt.

Ez biztosítja, hogy a felhasználók az eseményhurok egyéb feladatai miatti késedelmek nélkül látják a frissített adatokat.

A mikrofeladatok ilyen forgatókönyvekben történő használata megakadályozhatja a felhasználói felület megszakítását, és gyorsabb és gördülékenyebb interakciót biztosít az alkalmazásban.

Az eseményhurok következményei a webfejlesztés számára

Az eseményhurok megértése és funkcióinak használata elengedhetetlen a hatékony és érzékeny alkalmazások létrehozásához. Az eseményhurok aszinkron és párhuzamos képességeket biztosít, így hatékonyan kezelheti az alkalmazás összetett feladatait anélkül, hogy a felhasználói élményt veszélyeztetné.

A Node.js mindent biztosít, amire szüksége van, beleértve a webes dolgozókat is, hogy további párhuzamosságot érjenek el a JavaScript főszálán kívül.