¿Qué eres, Event Loop? O cómo funciona el bucle de eventos en el navegador Chrome

¿Qué crees que sucederá si ejecutas este código en la consola del navegador?

function foo() { setTimeout(foo, 0); } foo(); 

Y este?

 function foo() { Promise.resolve().then(foo); } foo(); 

Si, como yo, ha leído un montón de artículos sobre Event Loop, Main Thread, tareas, microtasks y más, pero le resulta difícil responder las preguntas anteriores, este artículo es para usted.

Entonces comencemos. El código para cada página HTML en el navegador se ejecuta en Main Thread . Main Thread es el hilo principal donde el navegador realiza JS, vuelve a dibujar, maneja las acciones del usuario y mucho más. Esencialmente, aquí es donde el motor JS está integrado en el navegador.

La forma más fácil de resolverlo es mirando el diagrama:


Figura 1

Vemos que el único lugar a través del cual las tareas pueden ingresar a la Pila de llamadas y completarse es Event Loop. Imagina que estabas en su lugar. Y su trabajo es mantener el ritmo de las tareas. Las tareas pueden ser de dos tipos:

  1. Personal: ejecución del código JavaScript principal en el sitio (en adelante asumiremos que ya se ha ejecutado)
  2. Tareas del cliente: Render, microtasks y Tasks

Lo más probable es que sus tareas personales sean priorizadas. Event Loop está de acuerdo con esto :) Queda por optimizar las tareas del cliente.

Por supuesto, lo primero que viene a la mente es dar prioridad a cada cliente y alinearlos. El segundo es determinar exactamente cómo se procesarán las tareas de cada cliente: una a la vez, todas a la vez, o tal vez en lotes.

Echa un vistazo a este diagrama:


Figura 2

Basado en este esquema, se construye todo el trabajo de Event Loop.
Después de que comenzamos a ejecutar cualquier script, la tarea con la ejecución de este script se coloca en la cola Tareas. A medida que se ejecuta este código, nos encontramos con tareas de diferentes clientes, que se colocan en la cola adecuada. Una vez completada la tarea de ejecución del script (tarea de Tareas), Event Loop pasa a Microtasks (después de la tarea de Tasks, Event Loop toma tareas de Microtasks). Event Loop toma tareas de él hasta que finalizan . Esto significa que si el tiempo de su adición es igual al tiempo de su ejecución, el Event Loop los rastrillará interminablemente.
Luego, va a Render y realiza tareas de él. El navegador optimiza las tareas de Render, y si considera que no hay necesidad de volver a dibujar nada en este ciclo, Event Loop simplemente irá más allá. Luego, Event Loop nuevamente toma tareas de Tareas y le pide solo una, la primera tarea en la cola , la pasa a CallStack y va más allá en el ciclo.

Si uno de los clientes no tenía tareas, Event Loop simplemente pasa a la siguiente. Y, por el contrario, si las tareas del cliente toman mucho tiempo, los clientes restantes esperarán su turno. Y si las tareas de algún cliente resultaron ser interminables, Call Stack se desborda y el navegador comienza a maldecir:


Figura 3

Ahora que entendemos cómo funciona Event Loop, es hora de descubrir qué sucede después de que se ejecutan los fragmentos de código al comienzo de este artículo.

 function foo() { setTimeout(foo, 0); } foo(); 

Vemos que la función foo se llama a sí misma recursivamente a través de setTimeout dentro, pero con cada llamada crea una tarea de cliente Tareas. Como recordamos, en el bucle de bucle de eventos, cuando se ejecuta la cola de tareas desde Tareas, solo se necesita 1 tarea en el bucle. Y luego están las tareas de Microtasks y Render. Por lo tanto, este fragmento de código no causará que Event Loop se vea afectado y para siempre realice sus tareas. Pero arrojará una nueva tarea para las Tareas del cliente en cada vuelta.

Intentemos ejecutar este script en el navegador Google Chrome. Para hacer esto, creé un documento HTML simple y conecté script.js con este fragmento de código. Después de abrir el documento, vaya a las herramientas del desarrollador, abra la pestaña Perfomance y haga clic en el botón "Iniciar perfilado y volver a cargar la página":


Figura 4

Vemos que las tareas de Tareas se realizan una a la vez, aproximadamente una vez cada 4 ms.

Considere el segundo rompecabezas:

 function foo() { Promise.resolve().then(foo); } foo(); 

Aquí vemos lo mismo que en el ejemplo anterior, pero llamar a foo agrega tareas de Microtasks, y todas se realizan hasta que finalizan. Esto significa que hasta que Event Loop los termine, no podrá pasar al siguiente cliente :( Y nuevamente vemos una imagen triste.

Eche un vistazo a esto en las herramientas de desarrollo:


Figura 5

Vemos que las microtasks se ejecutan aproximadamente una vez cada 0.1 ms, y esto es 40 veces más rápido que la cola de tareas. Todo porque se realizan todos a la vez. En nuestro ejemplo, la cola se mueve sin cesar. Para la visualización, lo reduje a 100,000 iteraciones.

Eso es todo!

Espero que este artículo te haya sido útil, y ahora entiendes cómo funciona Event Loop y qué está sucediendo en los ejemplos de código anteriores.

Bye :) Y hasta pronto. Si te gustó, dale me gusta y suscríbete a mi canal :)

Source: https://habr.com/ru/post/461401/


All Articles