Hoe werkt de Event Loop in JavaScript?

Hoewel het een grondige kennis van talen zoals C ++ en C vereist om volledige productiecode te schrijven, kan JavaScript vaak worden geschreven met slechts een basiskennis van wat er met de taal kan worden gedaan.


Concepten, zoals het doorgeven van callbacks naar functies of het schrijven van asynchrone code, zijn vaak niet zo moeilijk te implementeren, waardoor de meeste JavaScript-ontwikkelaars zich minder druk maken over wat er onder de motorkap gebeurt. Ze geven er gewoon niet om om de complexiteit te begrijpen die door de taal diep van hen is geabstraheerd.

Als JavaScript-ontwikkelaar wordt het steeds belangrijker om te begrijpen wat er echt onder de motorkap gebeurt en hoe de meeste van deze van ons onttrokken complexiteiten echt werken. Het helpt ons om beter geïnformeerde beslissingen te nemen, wat op zijn beurt onze codeprestaties drastisch kan verbeteren.

Dit artikel richt zich op een van de zeer belangrijke maar zelden begrepen concepten of termen in JavaScript. De EVENEMENT LUS!. 

Het schrijven van asynchrone code kan niet worden vermeden in JavaScript, maar waarom betekent een code die asynchroon wordt uitgevoerd eigenlijk? d.w.z. De Event Loop

Voordat we kunnen begrijpen hoe de gebeurtenislus werkt, moeten we eerst begrijpen wat JavaScript zelf is en hoe het werkt!

Wat is JavaScript?

Voordat we verder gaan, wil ik dat we een stap terug doen naar de basis. Wat is JavaScript eigenlijk? We zouden JavaScript kunnen definiëren als;

JavaScript is een geïnterpreteerde, niet-blokkerende, asynchrone, gelijktijdige taal van hoog niveau.

Wacht, wat is dit? Een boekachtige definitie? ��

Laten we het opsplitsen!

De sleutelwoorden hier met betrekking tot dit artikel zijn enkele draad, niet-blokkerend, gelijktijdig, en asynchroon.

Enkele draad

Een thread van uitvoering is de kleinste reeks geprogrammeerde instructies die onafhankelijk door een planner kan worden beheerd. Een programmeertaal is single-threaded, wat betekent dat deze slechts één taak of bewerking tegelijk kan uitvoeren. Dit betekent dat het een volledig proces van begin tot eind zou uitvoeren zonder dat de thread wordt onderbroken of gestopt.

In tegenstelling tot multi-threaded talen waarbij meerdere processen tegelijkertijd op verschillende threads kunnen worden uitgevoerd zonder elkaar te blokkeren.

Hoe kan JavaScript single-threaded zijn en blokkeert niet tegelijkertijd?

Maar wat betekent blokkeren??

Blokkeert niet

Er is niet één definitie van blokkeren; het betekent gewoon dingen die langzaam op de draad lopen. Dus niet-blokkeren betekent dingen die niet traag op de draad zijn.

Maar wacht, heb ik gezegd dat JavaScript op één thread wordt uitgevoerd? En ik zei ook dat het niet blokkeert, wat betekent dat de taak snel wordt uitgevoerd op de oproepstack? Maar hoe??? Hoe zit het met het uitvoeren van timers? Lussen?

Kom tot rust! We komen er zo wel achter ��.

Gelijktijdig

Gelijktijdigheid betekent dat de code gelijktijdig door meer dan één thread wordt uitgevoerd.

Oké, het wordt echt echt raar hoe kan JavaScript nu single-threaded zijn en tegelijkertijd gelijktijdig zijn? d.w.z. het uitvoeren van de code met meer dan één thread?

Asynchroon

Asynchrone programmering betekent dat de code wordt uitgevoerd in een gebeurtenislus. Als er een blokkering is, wordt de gebeurtenis gestart. De blokkeringscode blijft actief zonder de hoofduitvoeringsthread te blokkeren. Wanneer de blokkeringscode is voltooid, staat deze in de wachtrij als gevolg van de blokkeringsbewerkingen en worden ze teruggezet naar de stapel.

Maar JavaScript heeft een enkele thread? Wat vervolgens deze blokkerende code uitvoert terwijl andere codes in de thread worden uitgevoerd?

Laten we, voordat we verder gaan, een samenvatting geven van het bovenstaande.

  • JavaScript heeft één thread
  • JavaScript blokkeert niet, d.w.z. langzame processen blokkeren de uitvoering ervan niet
  • JavaScript is gelijktijdig, d.w.z. het voert de code in meer dan één thread tegelijkertijd uit
  • JavaScript is asynchroon, dat wil zeggen dat het ergens anders blokkerende code uitvoert.

Maar het bovenstaande klopt niet precies, hoe kan een single-threaded taal niet-blokkerend, gelijktijdig en asynchroon zijn?

Laten we een beetje dieper gaan, laten we gaan naar de JavaScript-runtime-engines, V8, misschien heeft het een aantal verborgen threads waarvan we ons niet bewust zijn.

V8-motor

De V8-engine is een krachtige, open-source runtime-engine voor webassemblage voor JavaScript, geschreven in C ++ door Google. De meeste browsers voeren JavaScript uit met de V8-engine en zelfs de populaire node js-runtime-omgeving gebruikt het ook.

In eenvoudig Engels is de V8 een C ++ – programma dat JavaScript-code ontvangt, compileert en uitvoert.

De V8 doet twee belangrijke dingen;

  • Heap geheugentoewijzing
  • Call stack uitvoeringscontext

Helaas was ons vermoeden onjuist. De V8 heeft slechts één oproepstapel, denk aan de oproepstapel als de draad.

Eén thread === één callstack === één uitvoering tegelijk.

Afbeelding – Hacker Noon

Aangezien V8 slechts één aanroepstack heeft, hoe werkt JavaScript dan gelijktijdig en asynchroon zonder de hoofduitvoeringsthread te blokkeren?

Laten we proberen erachter te komen door een eenvoudige maar veelvoorkomende asynchrone code te schrijven en deze samen te analyseren.

JavaScript voert elke code regel voor regel uit, achter elkaar (single-threaded). Zoals verwacht wordt de eerste regel hier in de console afgedrukt, maar waarom wordt de laatste regel vóór de time-outcode afgedrukt? Waarom wacht het uitvoeringsproces niet op de time-outcode (blokkering) alvorens door te gaan met het uitvoeren van de laatste regel?

Een andere thread lijkt ons te hebben geholpen die time-out uit te voeren, omdat we er vrij zeker van zijn dat een thread slechts één enkele taak op elk moment kan uitvoeren.

Laten we een kijkje nemen in de V8-broncode voor een poosje.

Wacht wat??!!! Er zijn geen timerfuncties in V8, geen DOM? Geen evenementen? Geen AJAX?…. Yeeeeessss!!!

Evenementen, DOM, timers, enz. Maken geen deel uit van de kernimplementatie van JavaScript, JavaScript voldoet strikt aan de Ecma Scripts-specificaties en er wordt vaak naar verschillende versies verwezen volgens de Ecma Scripts-specificaties (ES X).

Uitvoeringsworkflow

Evenementen, timers, Ajax-verzoeken worden allemaal aan de clientzijde geleverd door de browsers en worden vaak Web API genoemd. Zij zijn het die ervoor zorgen dat JavaScript met één thread niet-blokkerend, gelijktijdig en asynchroon is! Maar hoe?

Er zijn drie belangrijke secties in de uitvoeringsworkflow van elk JavaScript-programma, de callstack, de web-API en de taakwachtrij.

De Call Stack

Een stapel is een datastructuur waarbij het laatst toegevoegde element altijd het eerste is dat uit de stapel wordt verwijderd, je zou het kunnen zien als een stapel van een plaat waarin alleen de eerste plaat die als laatste is toegevoegd als eerste kan worden verwijderd. Een Call Stack is gewoon niets anders dan een stack datastructuur waar taken of code dienovereenkomstig worden uitgevoerd.

Laten we eens kijken naar het onderstaande voorbeeld;

Bron – https://youtu.be/8aGhZQkoFbQ

Wanneer u de functie printSquare () aanroept, wordt deze op de oproepstack geduwd, de functie printSquare () roept de functie square () aan. De functie square () wordt op de stapel gedrukt en roept ook de functie multiply () aan. De vermenigvuldigingsfunctie wordt op de stapel gedrukt. Aangezien de vermenigvuldigingsfunctie terugkeert en het laatste is dat naar de stapel is gepusht, wordt het eerst opgelost en wordt het van de stapel verwijderd, gevolgd door de functie square () en vervolgens de functie printSquare ().

De Web API

Dit is waar code die niet wordt afgehandeld door de V8-engine wordt uitgevoerd om de hoofduitvoeringsthread niet te “blokkeren”. Wanneer de Call Stack een web-API-functie tegenkomt, wordt het proces onmiddellijk overgedragen aan de Web API, waar het wordt uitgevoerd en de Call Stack vrijmaakt om andere bewerkingen uit te voeren tijdens de uitvoering.

Laten we teruggaan naar ons setTimeout-voorbeeld hierboven;

Wanneer we de code uitvoeren, wordt de eerste console.log-regel naar de stapel gepusht en krijgen we onze output bijna onmiddellijk.Als de time-out wordt bereikt, worden timers afgehandeld door de browser en maken ze geen deel uit van de kernimplementatie van V8, het wordt gepusht in plaats daarvan naar de Web API, waardoor de stapel wordt vrijgemaakt zodat deze andere bewerkingen kan uitvoeren.

Terwijl de time-out nog steeds loopt, gaat de stapel door naar de volgende actielijn en voert de laatste console.log uit, wat verklaart waarom we die laten uitvoeren vóór de timeruitvoer. Zodra de timer is voltooid, gebeurt er iets. De console.log in en timer verschijnt op magische wijze opnieuw in de oproepstapel!

Hoe?

De Event Loop

Voordat we de gebeurtenislus bespreken, gaan we eerst door de functie van de taakwachtrij.

Terug naar ons time-outvoorbeeld: zodra de Web API klaar is met het uitvoeren van de taak, wordt deze niet automatisch teruggeduwd naar de Call Stack. Het gaat naar de Taakwachtrij. 

Een wachtrij is een gegevensstructuur die werkt volgens het First in First out-principe, dus als taken in de wachtrij worden gepusht, komen ze in dezelfde volgorde uit. Taken die zijn uitgevoerd door de Web API’s, die naar de Taakwachtrij worden gepusht, en dan teruggaan naar de Oproepstapel om hun resultaat te laten afdrukken.

Maar wacht. WAT DE HECK IS DE EVENEMENT LUS???

Bron – https://youtu.be/8aGhZQkoFbQ

De gebeurtenislus is een proces dat wacht totdat de gespreksstapel duidelijk is voordat callbacks vanuit de taakwachtrij naar de gespreksstapel worden gepusht. Zodra de stapel leeg is, activeert en controleert de gebeurtenislus de taakwachtrij op beschikbare terugbelverzoeken. Als die er zijn, wordt deze naar de Call Stack geduwd, wacht hij tot de Call Stack weer duidelijk is en herhaalt hij hetzelfde proces.

Bron – https://www.quora.com/How-does-an-event-loop-work/answer/Timothy-Maxwell

Het bovenstaande diagram toont de basisworkflow tussen de Event Loop en de taakwachtrij.

Conclusie

Hoewel dit een zeer eenvoudige inleiding is, geeft het concept van asynchrone programmering in JavaScript voldoende inzicht om duidelijk te begrijpen wat er onder de motorkap gebeurt en hoe JavaScript in staat is om gelijktijdig en asynchroon te werken met slechts één enkele thread.

JavaScript is altijd op aanvraag en als je nieuwsgierig bent om te leren, raad ik je aan dit te bekijken Udemy natuurlijk.

Jeffrey Wilson Administrator
Sorry! The Author has not filled his profile.
follow me
    Like this post? Please share to your friends:
    Adblock
    detector
    map