Geekflare cuenta con el apoyo de nuestra audiencia. Podemos ganar comisiones de afiliados comprando enlaces en este sitio.
Comparte en:

¿Cómo funciona Event Loop en JavaScript?

bucle javascript
Escáner de seguridad de aplicaciones web Invicti – la única solución que ofrece verificación automática de vulnerabilidades con Proof-Based Scanning™.

Si bien puede requerir una comprensión profunda de lenguajes como C ++ y C para escribir código de producción a gran escala, JavaScript a menudo se puede escribir con solo una comprensión básica de lo que se puede hacer con el lenguaje.

Los conceptos, como pasar devoluciones de llamada a funciones o escribir código asincrónico, a menudo no son tan difíciles de implementar, lo que hace que la mayoría de los desarrolladores de JavaScript se preocupen menos por lo que sucede bajo el capó. Simplemente no les importa comprender las complejidades que el lenguaje ha abstraído profundamente de ellos.

Como desarrollador de JavaScript, es cada vez más importante comprender lo que realmente sucede bajo el capó y cómo la mayoría de estas complejidades abstraídas de nosotros realmente funcionan. Nos ayuda a tomar decisiones más informadas, lo que, a su vez, puede aumentar drásticamente el rendimiento de nuestro código.

Este artículo se centra en uno de los conceptos o términos muy importantes pero que rara vez se comprenden en JavaScript. los ¡EVENTO BUCLE !. 

Escribir código asincrónico no se puede evitar en JavaScript, pero ¿por qué realmente significa un código que se ejecuta de forma asincrónica? es decir El bucle de eventos

Antes de que podamos entender cómo funciona el bucle de eventos, primero tenemos que entender qué es JavaScript en sí y cómo funciona.

What is JavaScript?

Antes de continuar, me gustaría que retrocedamos un paso hacia lo básico. ¿Qué es realmente JavaScript? Podríamos definir JavaScript como;

JavaScript es un lenguaje concurrente, asíncrono, no bloqueante, interpretado, de alto nivel.

Espera, ¿qué es esto? ¿Una definición libresca? 🤔

¡Vamos a analizarlo!

Las palabras clave aquí con respecto a este artículo son de un solo hilo, no bloqueante, concurrente, y asincrónico.

Hilo único

Un hilo de ejecución es la secuencia más pequeña de instrucción programada que puede ser administrada de forma independiente por un programador. Un lenguaje de programación es de un solo subproceso, lo que significa que solo puede realizar una tarea u operación a la vez. Esto significa que ejecutaría un proceso completo de principio a fin sin que el hilo se interrumpa o detenga.

A diferencia de los lenguajes de subprocesos múltiples, en los que se pueden ejecutar varios procesos en varios subprocesos al mismo tiempo sin bloquearse entre sí.

¿Cómo puede JavaScript ser de un solo subproceso y sin bloqueo ¿al mismo tiempo?

Pero, ¿qué significa bloquear?

Sin bloqueo

No existe una definición única de bloqueo; simplemente significa cosas que se están ejecutando lentamente en el hilo. Entonces, no bloquear significa cosas que no son lentas en el hilo.

Pero espera, ¿dije que JavaScript se ejecuta en un solo hilo? Y también lo dije sin bloqueo, lo que significa que la tarea se ejecuta rápidamente en la pila de llamadas. ¿¿¿Pero cómo??? ¿Qué tal cuando ejecutamos temporizadores? Bucles?

¡Relajarse! Lo averiguaremos en un momento 😉.

Concurrente

Simultaneidad significa que el código se está ejecutando simultáneamente por más de un hilo.

Está bien, las cosas se están poniendo realmente extraño ahora, ¿cómo puede JavaScript ser de un solo subproceso y ser concurrente al mismo tiempo? es decir, ¿ejecutar su código con más de un hilo?

Asincrónico

La programación asincrónica significa que el código se ejecuta en un bucle de eventos. Cuando hay una operación de bloqueo, se inicia el evento. El código de bloqueo sigue ejecutándose sin bloquear el hilo de ejecución principal. Cuando el código de bloqueo termina de ejecutarse, la cola es el resultado de las operaciones de bloqueo y las devuelve a la pila.

¿Pero JavaScript tiene un solo hilo? Entonces, ¿qué ejecuta este código de bloqueo mientras permite que se ejecuten otros códigos en el hilo?

Antes de continuar, repasemos lo anterior.

  • JavaScript es de un solo subproceso
  • JavaScript no bloquea, es decir, los procesos lentos no bloquean su ejecución
  • JavaScript es concurrente, es decir, ejecuta su código en más de un hilo al mismo tiempo.
  • JavaScript es asincrónico, es decir, ejecuta código de bloqueo en otro lugar.

Pero lo anterior no cuadra exactamente, ¿cómo puede un lenguaje de un solo subproceso ser no bloqueante, concurrente y asincrónico?

Profundicemos un poco más, bajemos a los motores en tiempo de ejecución de JavaScript, V8, tal vez tenga algunos hilos ocultos que no conocemos.

Motor V8

El motor V8 es un motor en tiempo de ejecución de ensamblaje web de código abierto y alto rendimiento para JavaScript escrito en C ++ por Google. La mayoría de los navegadores ejecutan JavaScript usando el motor V8, e incluso el popular entorno de tiempo de ejecución de node js también lo usa.

En inglés simple, el V8 es un programa C ++, que recibe código JavaScript, lo compila y lo ejecuta.

El V8 hace dos cosas importantes;

  • Asignación de memoria de pila
  • Contexto de ejecución de la pila de llamadas

Lamentablemente, nuestra sospecha estaba equivocada. El V8 tiene solo una pila de llamadas, piense en la pila de llamadas como el hilo.

Un hilo === una pila de llamadas === una ejecución a la vez.

Imagen - Hacker Noon

Dado que V8 tiene solo una pila de llamadas, ¿cómo se ejecuta JavaScript de manera concurrente y asincrónica sin bloquear el hilo de ejecución principal?

Intentemos averiguarlo escribiendo un código asincrónico simple pero común y analizándolo juntos.

JavaScript ejecuta cada código línea por línea, uno tras otro (un solo subproceso). Como era de esperar, la primera línea se imprime en la consola aquí, pero ¿por qué se imprime la última línea antes del código de tiempo de espera? ¿Por qué el proceso de ejecución no espera el código de tiempo de espera (bloqueo) antes de continuar para ejecutar la última línea?

Algún otro hilo parece habernos ayudado a ejecutar ese tiempo de espera, ya que estamos bastante seguros de que un hilo solo puede ejecutar una sola tarea en cualquier momento.

Echemos un vistazo al Código fuente V8 por un momento.

¡¡¡¿¿Esperar lo??!!! ¿No hay funciones de temporizador en V8, no DOM? ¿No hay eventos? ¿Sin AJAX?…. Yeeeeessss !!!

Los eventos, DOM, temporizadores, etc. no forman parte de la implementación central de JavaScript, JavaScript se ajusta estrictamente a las especificaciones de Ecma Scripts y a menudo se hace referencia a varias versiones de él de acuerdo con sus Especificaciones de Ecma Scripts (ES X).

Execution Workflow

Los navegadores proporcionan eventos, temporizadores y solicitudes Ajax en el lado del cliente y, a menudo, se denominan API web. ¡Son los que permiten que el JavaScript de un solo subproceso sea no bloqueante, concurrente y asincrónico! ¿Pero cómo?

Hay tres secciones principales para el flujo de trabajo de ejecución de cualquier programa JavaScript, la pila de llamadas, la API web y la cola de tareas.

La pila de llamadas

Una pila es una estructura de datos en la que el último elemento agregado es siempre el primero en eliminarse de la pila, podría pensar en ella como una pila de un plato en el que solo se puede quitar primero el primer plato que fue el último agregado. Una pila de llamadas no es más que una estructura de datos de pila donde las tareas o el código se ejecutan en consecuencia.

Consideremos el siguiente ejemplo;

Fuente: https://youtu.be/8aGhZQkoFbQ

Cuando llamas a la función printSquare() , se inserta en la pila de llamadas, printSquare() la función llama al cuadrado() función. los square() La función se inserta en la pila y también llama al multiply() función. La función de multiplicar se inserta en la pila. Dado que la función de multiplicar regresa y es lo último que se envió a la pila, se resuelve primero y se elimina de la pila, seguido de la square() función y luego el printSquare() función.

La API web

Aquí es donde se ejecuta el código que no es manejado por el motor V8 para no "bloquear" el hilo de ejecución principal. Cuando la pila de llamadas encuentra una función de la API web, el proceso se entrega inmediatamente a la API web, donde se está ejecutando y libera la pila de llamadas para realizar otras operaciones durante su ejecución.

Volvamos a nuestro setTimeout ejemplo anterior;

Cuando ejecutamos el código, la primera línea console.log se envía a la pila y obtenemos nuestro resultado casi de inmediato, al llegar al tiempo de espera, los temporizadores son manejados por el navegador y no forman parte de la implementación central de V8, se empuja a la API web en su lugar, liberando la pila para que pueda realizar otras operaciones.

Mientras el tiempo de espera aún se está ejecutando, la pila avanza a la siguiente línea de acción y ejecuta el último console.log, lo que explica por qué obtenemos eso antes de la salida del temporizador. Una vez que se completa el temporizador, sucede algo. El console.log in y luego el temporizador aparece mágicamente en la pila de llamadas nuevamente.

¿Cómo?

El bucle de eventos

Antes de discutir el ciclo de eventos, veamos primero la función de la cola de tareas.

Volviendo a nuestro ejemplo de tiempo de espera, una vez que la API web termina de ejecutar la tarea, no la devuelve automáticamente a la pila de llamadas. Va al Cola de tareas. 

Una cola es una estructura de datos que funciona según el principio Primero en entrar, primero en salir, de modo que a medida que las tareas se introducen en la cola, salen en el mismo orden. Las tareas que han sido ejecutadas por las API web, que se envían a la cola de tareas, luego regresan a la pila de llamadas para imprimir su resultado.

Pero espera. ¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿?? ¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿???

Fuente: https://youtu.be/8aGhZQkoFbQ

El bucle de eventos es un proceso que espera a que la pila de llamadas se elimine antes de enviar devoluciones de llamada de la cola de tareas a la pila de llamadas. Una vez que la pila está limpia, el ciclo de eventos se activa y verifica la cola de tareas para ver si hay devoluciones de llamada disponibles. Si hay alguno, lo empuja a la Pila de llamadas, espera a que la Pila de llamadas se borre nuevamente y repite el mismo proceso.

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

El diagrama anterior muestra el flujo de trabajo básico entre Event Loop y Task Queue.

Conclusión

Si bien esta es una introducción muy básica, el concepto de programación asincrónica en JavaScript brinda suficiente información para comprender claramente lo que está sucediendo bajo el capó y cómo JavaScript puede ejecutarse de manera concurrente y asincrónica con un solo hilo.

JavaScript está siempre bajo demanda, y si tiene curiosidad por aprender, le aconsejo que consulte este Curso Udemy.

Gracias a nuestros patrocinadores
Más lecturas interesantes sobre el desarrollo
Impulse su negocio
Algunas de las herramientas y servicios para ayudar a que su negocio crezca.
  • Invicti utiliza Proof-Based Scanning™ para verificar automáticamente las vulnerabilidades identificadas y generar resultados procesables en cuestión de horas.
    Prueba Invicti
  • Web scraping, proxy residencial, administrador de proxy, desbloqueador web, rastreador de motores de búsqueda y todo lo que necesita para recopilar datos web.
    Prueba Brightdata
  • Semrush es una solución de marketing digital todo en uno con más de 50 herramientas en SEO, redes sociales y marketing de contenido.
    Prueba Semrush
  • Intruder es un escáner de vulnerabilidades en línea que encuentra debilidades de ciberseguridad en su infraestructura, para evitar costosas filtraciones de datos.
    Intente Intruder