Your web browser is out of date. Update your browser for more security, speed and the best experience on this site.

The Browser in the loop

De Event Loop is essentieel bij de interactie tussen JavaScript en je webpagina’s. Iedereen die ontwikkelt voor webbrowsers weet wat de Event Loop is, maar toch blijft het een bron van veel problemen.

Deel dit artikel
Java

ALLES WAT JE MOET WETEN OVER DE EVENT LOOP VAN BROWSERS

De Event Loop is essentieel bij de interactie tussen JavaScript en je webpagina’s. Iedereen die ontwikkelt voor webbrowsers weet wat de Event Loop is, maar toch blijft het een bron van veel problemen. Pagina’s die vastlopen, applicaties die vervelend traag vooruit gaan, elementen die plots verspringen… vaak heeft het te maken met een foute manier om de Event Loop aan te roepen. Met ook dank aan Jake Archibald gaan we een paar typische scenario’s bekijken.

By Joey Comhaire – Java Developer Axxes.

WAAROM DE EVENT LOOP?

Webpagina’s worden opgebouwd en beheerd door een enkele hoofd-thread. Om ervoor te zorgen dat alles vlotjes verloopt, wordt code op de thread uitgevoerd in een vaste volgorde. Dat zorgt voor enkele uitdagingen. Als een element in je thread er lang over doet om te laden, blokkeert het ook de rest van de code.

Het gebruik van setTimeout in JavaScript is daar een mooi voorbeeld van. Gebruik je die functie om een pauze van een paar miliseconden in te lassen, dan wordt de rest van je code ook vertraagd uitgevoerd. Je pagina laadt dus trager en dat zorgt voor een zwakke gebruikservaring. Liefst laat je setTimeout op een aparte thread wachten en daarna voer je de uitgestelde callback uit op de main thread.

De Event Loop leidt dit proces in goede banen door gebruik te maken van wachtrijen waarop je verschillende soorten taken parkeert. De Event Loop verwerkt de elementen op deze wachtrijen in vaste volgorde. Er zijn drie wachtrijen:

  1. De taken-wachtrij (task queue, callback queue)
  2. Render-stappen
  3. De microtaken-wachtrij (microtask queue, job queue)
1. Taken-wachtrij

Op de wachtrij voor taken, beter gekend als de task queue of callback queue, parkeert de Event Loop de asynchrone JavaScript-taken die de browser vraagt om uit te voeren. Dat kan een setTimeout zijn, een onClick of iets dergelijks. De Event Loop draait rond en voert per revolutie een taak uit wanneer er geen andere code meer in de browser wordt gedraaid. Het uitvoeren hiervan gebeurt op een specifiek moment in de loop. Dat is belangrijk want ze bepaalt de volgorde waarin de overige wachtrijen wordt uitgevoerd. Bekijk zeker dit stukje in de sessie van Jake Archibald <

> waarin hij het concept van de Event Loop en taken-wachtrij illustreert.

2. Render-stappen

Wat op de taken-wachtrij wordt verwerkt, moet ook gevisualiseerd worden. Daarvoor dienen de render-stappen. Deze wachtrij komt na de taken – hoewel voor of na niet echt bestaat in een loop – en bestaat uit vier stappen:

  1. Het verwerken van requestAnimationFrame
  2. Stijlberekeningen volgens de CSS
  3. Layout-rendering: waar komt wat op de pagina?
  4. Verven: het maken van de pixel-data

Net zoals de volgorde en timing van de wachtrijen, is ook de volgorde van deze stappen belangrijk om te onthouden om bepaalde problemen of bugs te begrijpen en op te sporen.

3. Microtaken-wachtrij

Om bepaalde veranderingen te monitoren, introduceerde JavaScript mutation events. Dat werden later mutation observers en de promise-functie. Voor dit soort zaken werd een nieuwe wachtrij gemaakt: de microtaken-wachtrij (de microtask queue of job queue). Hoewel deze ook een vaste plaats in de loop heeft, zal je die rij daar niet vaak tegen komen. De microtaken worden namelijk uitgevoerd als er geen ander JavaScript loopt in de Event Loop, meestal na afronding van een taak.


HOE ELKE WACHTRIJ WORDT VERWERKT

Belangrijk voor foutopsporing is begrijpen hoe elke wachtrij in de Event Loop wordt verwerkt. De Loop gaat namelijk met elke rij anders om.

  1. Op de taken-wachtrij worden items een voor een verwerkt volgens een FIFO-principe, dus First In, First Out. Na het verwerken van een taak gaat de Event Loop verder naar de andere wachtrijen. Pas als daar niets meer te doen valt, wordt de volgende taak aangepakt.
  2. Voor de render-stappen gebeurt iets anders. Alle taken die op het moment van de verwerking in de wachtrij staan, worden in één keer afgerond volgens FIFO. Nieuwe taken die tijdens het verwerken worden toegevoegd, moeten wachten op de volgende revolutie van de Event Loop.
  3. De microtaken-wachtrij pakt het weer anders aan. Ook hier loopt het volgens FIFO en net zoals bij de render-stappen worden alle wachtende taken afgerond alvorens de Event Loop verder gaat. Let wel op, want de Event Loop blijf microtaken verwerken tot ze allemaal weg zijn. Blijf je dus microtaken toevoegen tijdens de verwerking, dan blijft de Event Loop alleen op deze wachtrij werken en nergens anders.


WAAROM HET BELANGRIJK IS OM DE VOLGORDE EN VERWERKING TE BEGRIJPEN

Je vraagt je misschien af waarom je al deze informatie nodig hebt. Het antwoord is simpel: je schrijft er betere code door met minder kans op bugs. Verschijnt er toch een occasionele fout, dan kom je sneller tot een oplossing door te begrijpen wat zich in de achtergrond afspeelt. We illustreren het even met een paar voorbeelden.

– Volgorde van de wachtrijen

Stel dat je een knop maakt met een onClick-element dat een standaard oneindige JavaScript-loop initieert. Je Event Loop krijgt de boodschap om die taak uit te voeren. Normaal gezien wordt de taak uitgevoerd en gaat de Loop verder langs de render-stappen om de wijzigingen van de taak ook visueel te maken. Maar aan de taak die de Loop aanpakt zit geen einde, het is een oneindige loop. Het betekent dat de Event Loop in de taken-wachtrij blijft en nooit doorloopt naar de render-stappen. Het gevolg: je webpagina bevriest en is niet meer responsief.

– Verwerking van de wachtrijen

Omdat elke wachtrij het anders aanpakt, kunnen ook daar problemen ontstaan als je de verwerking niet volgt zoals het zou moeten. Wanneer je microtaken codeert die telkens een nieuwe microtaak aanmaken, zal je zien dat je webpagina vast slaat. Waarom? Omdat de Event Loop de taken op de microtaken-wachtrij blijft verwerken tot deze leeg is. Dat in tegenstelling tot de taken-wachtrij waar de Event Loop na het verwerken van een taak zijn weg verder vervolgt. Het gevolg is dus dat de Event Loop een oneindige reeks microtaken blijft verwerken en nooit verder gaat naar de andere wachtrijen.

Er zijn nog tal van andere voorbeelden aan te halen die het belang van het kennen van de volgorde en verwerking van de Event Loop illustreren. Jake Archibald, die we eerder al aanhaalden, visualiseert er een aantal in zijn talk op JSConf.Asia. Bekijk deze zeker even als je er nog zoekt.

Benieuwd naar meer Axxes Insights?

Joey Comhaire

Joey Comhaire

Competence Coach - Frontend

Hulp nodig met een GraphQl implementatie?

Onze experts staan klaar om je verder te helpen.

contacteer ons
Axxes