Buscar..
El bucle de eventos en un navegador web.
La gran mayoría de los entornos modernos de JavaScript funcionan de acuerdo con un bucle de eventos . Este es un concepto común en la programación de computadoras que esencialmente significa que su programa espera continuamente que sucedan cosas nuevas y, cuando lo hacen, reacciona ante ellas. El entorno del host llama a su programa, generando un "turno" o "tick" o "tarea" en el bucle de eventos, que luego se ejecuta hasta su finalización . Cuando ese turno ha finalizado, el entorno de host espera que ocurra algo más, antes de que todo esto comience.
Un ejemplo simple de esto está en el navegador. Considere el siguiente ejemplo:
<!DOCTYPE html> <title>Event loop example</title> <script> console.log("this a script entry point"); document.body.onclick = () => { console.log("onclick"); }; setTimeout(() => { console.log("setTimeout callback log 1"); console.log("setTimeout callback log 2"); }, 100); </script>
En este ejemplo, el entorno host es el navegador web.
- El analizador de HTML ejecutará primero el
<script>
. Se ejecutará hasta su finalización. - La llamada a
setTimeout
le dice al navegador que, después de 100 milisegundos, debe poner en cola una tarea para realizar la acción dada. - Mientras tanto, el bucle de eventos es responsable de verificar continuamente si hay algo más que hacer: por ejemplo, renderizar la página web.
- Después de 100 milisegundos, si el bucle de eventos no está ocupado por alguna otra razón, verá la tarea que
setTimeout
pone en cola y ejecuta la función, registrando esas dos declaraciones. - En cualquier momento, si alguien hace clic en el cuerpo, el navegador publicará una tarea en el bucle de eventos para ejecutar la función del controlador de clic. El bucle de eventos, a medida que avanza continuamente para comprobar qué hacer, verá esto y ejecutará esa función.
Puede ver cómo en este ejemplo hay varios tipos diferentes de puntos de entrada en el código JavaScript que invoca el bucle de eventos:
- El elemento
<script>
se invoca inmediatamente - La tarea
setTimeout
se publica en el bucle de eventos y se ejecuta una vez - La tarea del controlador de clics puede publicarse muchas veces y ejecutarse cada vez
Cada vuelta del bucle de eventos es responsable de muchas cosas; solo algunos de ellos invocarán estas tareas de JavaScript. Para detalles completos, vea la especificación de HTML
Una última cosa: ¿qué queremos decir con decir que cada tarea de bucle de eventos "se ejecuta hasta completarse"? Queremos decir que generalmente no es posible interrumpir un bloque de código que está en cola para ejecutarse como una tarea, y nunca es posible ejecutar código intercalado con otro bloque de código. Por ejemplo, incluso si hizo clic en el momento perfecto, nunca podría obtener el código anterior para iniciar sesión en "onclick"
entre los dos setTimeout callback log 1/2"
s. Esto se debe a la forma en que funciona la publicación de tareas; es cooperativo y basado en la cola, en lugar de preventivo.
Operaciones asíncronas y el bucle de eventos.
Muchas operaciones interesantes en entornos comunes de programación de JavaScript son asíncronas. Por ejemplo, en el navegador vemos cosas como
window.setTimeout(() => { console.log("this happens later"); }, 100);
y en Node.js vemos cosas como
fs.readFile("file.txt", (err, data) => { console.log("data"); });
¿Cómo encaja esto con el bucle de eventos?
Cómo funciona esto es que cuando se ejecutan estas instrucciones, le dicen al entorno del host (es decir, el navegador o el tiempo de ejecución de Node.js, respectivamente) que se apaguen y hagan algo, probablemente en otro hilo. Cuando el entorno de host termine de hacer eso (respectivamente, esperando 100 milisegundos o leyendo el archivo file.txt
) publicará una tarea en el bucle de eventos, diciendo "llamar a la devolución de llamada que recibí anteriormente con estos argumentos".
El bucle de eventos está ocupado haciendo lo suyo: renderizar la página web, escuchar las opiniones de los usuarios y buscar continuamente las tareas publicadas. Cuando vea estas tareas publicadas para llamar a las devoluciones de llamada, volverá a llamar a JavaScript. ¡Así es como se obtiene el comportamiento asíncrono!