Inmersión profunda en Javascript Internals
Funcionamiento interno del motor Javascript, bucle de eventos, API web, colas de eventos y devoluciones de llamada.
Introducción
¿Alguna vez te has imaginado qué hubiera pasado si no hubiera Javascript? En ausencia de Javascript, no podría reproducir películas en Netflix, comprar en Amazon o ver videos en Youtube. Casi todos los demás sitios web usan Javascript y hacen que la página web sea interactiva.
Antes de que se inventara Javascript, Internet solo consistía en páginas HTML simples . HTML y CSS dan estructura y estilo a una página web. Pero Javascript hace que la página web sea dinámica . Puede ingresar sus credenciales e iniciar sesión en un sitio web, realizar transacciones en línea o jugar juegos. Javascript hace que todo suceda.
Una de las encuestas realizadas en Stack-overflow mostró que Javascript tiene la mayor cantidad de repositorios en GitHub. Cada año, se desarrollan nuevos marcos y bibliotecas en Javascript. El idioma realmente ha transformado Internet y ha simplificado la vida de las personas.
Fondo
Hace dos años, estaba trabajando en un proyecto paralelo y usé Javascript por primera vez. Siendo un programador experimentado desde la última década, adquirí un buen conocimiento de la sintaxis y desarrollé un buen dominio en tres meses.
Con el paso de los meses, la página web que había desarrollado no funcionaba bien. Tardó mucho tiempo en cargar y comenzó a impactar a los clientes. Entonces, hice una inmersión profunda para identificar la causa raíz.
Después de pasar noches sin dormir, finalmente estaba desesperado y estaba a punto de rendirme. Sin embargo, decidí hacer un último intento. Finalmente, pensé en obtener una comprensión profunda de cómo funciona Javascript internamente. Recomendé muchos recursos y finalmente pude corregir el error en mi código en dos días.
Los ingenieros generalmente se enfocan en construir cosas nuevas. Las herramientas y los marcos que utilizamos nos ocultan la mayor parte de la complejidad. En nuestro viaje, tendemos a olvidar cómo funcionan realmente las cosas entre bastidores. Es necesario conocer el funcionamiento interno de cualquier herramienta que utilicemos. Tener una buena comprensión de los aspectos internos nos ayuda a reducir el problema y llegar a una solución pragmática.
En este artículo, veremos lo que sucede detrás de escena cuando el navegador ejecuta Javascript. Echaremos un vistazo al motor Javascript y entenderemos su funcionamiento. Veremos los diferentes componentes involucrados en el tiempo de ejecución de Javascript y obtendremos claridad sobre el bucle de eventos y la cola de eventos. Aunque estos términos pueden ser nuevos para usted, el artículo intentará simplificar cada uno de ellos. Comencemos con nuestra búsqueda para dominar los aspectos internos de Javascript.
JavaScript
Javascript es un lenguaje interpretado de alto nivel. A diferencia de C o C++, no tenemos que compilar código Javascript y luego ejecutarlo. El código Javascript se compila primero en código de bytes y luego se traduce a código de nivel de máquina.
Los lenguajes avanzados como Java, C, C++, C# admiten subprocesos múltiples. Estos lenguajes permiten a los programadores crear múltiples subprocesos y ejecutar las tareas en diferentes subprocesos. Por lo tanto, podemos generar tareas en múltiples CPU y utilizar eficientemente los recursos informáticos.
Por el contrario, Javascript es de un solo subproceso. Esto significa que solo hay un único hilo de ejecución en un momento dado. En caso de que ejecute una función javascript de toma de tiempo, la página web se congelará. Es posible que haya visto que el sitio web no responde muchas veces mientras navegaba.
Hagamos una demostración rápida y veamos el funcionamiento en acción. He abierto Twitter y puedo hacer clic en las pestañas individuales como Trending, News, Sportsetc.
Ahora, en mi developerconsola, estoy escribiendo una función que contiene un bucle infinito . A continuación se muestra la definición de la función.
function infiniteLoop() {
for(i=0; i < 100000; ) {
}
}
infiniteLoop()
El siguiente GIF muestra que no puedo cambiar la pestaña a Sportso Entertaintment.
Dado que la función contiene un ciclo infinito, seguirá ejecutándose sin cesar. Cuando selecciono diferentes pestañas, se supone que el navegador maneja el clickevento y, en consecuencia, muestra el contenido de la pestaña en la que se hizo clic. No puedo seleccionar ninguna otra pestaña porque Javascript ya está ejecutando la función infiniteLoop.
Como se ve en el ejemplo anterior, solo podemos ejecutar una función a la vez en Javascript. Ahora, puede preguntarse, ¿cómo es que el navegador puede cargar sitios web complejos en una fracción de segundos?
En las secciones siguientes entenderemos cómo Javascript hace esta magia entre bastidores. Ahora comprendamos el núcleo de Javascript, es decir, el motor Javascript.
Motor Javascript
Cada navegador proporciona su propio motor Javascript. Por ejemplo: - Chrome usa el motor V8, mientras que Firefox usa el motor SpiderMonkey. El Motor es responsable de ejecutar el código Javascript línea por línea. A continuación se muestra una lista de navegadores populares y sus motores Javascript.
El motor Javascript consiste en un montón y una pila . Comprendamos el funcionamiento de estos dos elementos.
Montón
El Heap es responsable de almacenar las definiciones de funciones, variables de objetos. Contiene todos los objetos a los que hace referencia el código.
Los objetos se crean dinámicamente en el montón. El funcionamiento es similar a java. Cada vez que una función hace referencia al objeto, se obtiene del montón.
function bar() {
var player = { "firstName": "Shubhman",
"lastName": "Gill"
}
var teams = ["India", "NewZealand"]
i =0
a = 10
console.log("In the function bar")
}
bar()
Objects on Heap
Pila
La pila es una estructura de datos LIFO (último en entrar, primero en salir). Cada vez que se ejecuta una función, las variables locales de la función se colocan en la pila. Una vez que la función completa su ejecución, se elimina de la pila. Si una función llama a una nueva función durante la ejecución, la nueva función también se coloca en la pila. El motor ejecuta la función que se encuentra en la parte superior de la pila.
Las funciones que están en la parte inferior de la pila reanudan su ejecución una vez que regresan todas las funciones que están arriba. En caso de que una función arroje un error, se imprime un seguimiento de la pila en el archivo console. El seguimiento de la pila consta de una cadena de funciones que se llamaron cuando se lanzó una excepción. Echemos un vistazo a un ejemplo.
Voy a ejecutar el código anterior en mi navegador. Y agregue un punto de interrupción en la función city.
Como se vio anteriormente, al ejecutar el script, se detuvo en el punto de interrupción en la función city. En el lado derecho, en la Call Stacksección, puede ver la cityfunción en la parte superior.
consta Call Stackde todas las funciones invocadas hasta ahora. Y la función más reciente se coloca en la parte superior. Una vez que la función completa su ejecución, se elimina de la pila.
Puede ver en la imagen a continuación, la función cityse elimina y la ejecución continúa para la función streeten la línea número 9.
Como se vio anteriormente, Javascript solo puede ejecutar una función a la vez y solo hay un hilo de ejecución. No puede ejecutar varias funciones simultáneamente en la pila de ejecución.
Digamos que tenemos una función que realiza una HTTPllamada y obtiene datos de otro sitio web. ¿Qué pasaría si el servidor es lento y la función tarda mucho en ejecutarse? No podremos ejecutar ninguna otra función y la experiencia del usuario sería muy mala.
¿Sucede esto en el mundo real? No, los sitios web complejos como Facebook.com , Twitter.com , Amazon.com , etc. ejecutan toneladas de código Javascript sin afectar la experiencia del usuario. Para entender cómo, profundizaremos en el tiempo de ejecución de Javascript.
Tiempo de ejecución de Javascript
Javascript nos proporciona varias API para obtener datos del servidor, manipular el DOM o ejecutar funciones usando un temporizador. Debido a la naturaleza de subproceso único de Javascript, puede detener la representación de un sitio web, lo que provoca un rendimiento deficiente. Sin embargo, el tiempo de ejecución de Javascript garantiza que esto no suceda. Entendamos esto con un ejemplo.
Puedes adivinar cuál será el resultado del siguiente código: -
¿ Se getSubTitlesimprimirá después de imprimir getActors? Y después de llamar setTimeout, ¿se detendrá el código?
El siguiente es el resultado generado al ejecutar el código anterior: -
Como se ve arriba, se getSubTitlesimprimió primero y 4 segundos después, getActorsse imprimió. Aunque, la función setTimeoutesperó durante 4 segundos, pero aún ejecutó la función posterior getSubTitlesantes y el código no esperó. Ahora entendamos lo que sucedió detrás de escena.
API web
No encontrará la implementación de funciones como setTimeout, ni fetchen ninguna parte del código fuente de Javascript. Estas funciones son proporcionadas por el navegador y no forman parte de Javascript. La implementación diferiría para cada navegador.
El navegador proporciona funciones para realizar llamadas de red, manipular el DOM, procesar audio, videos, etc. Estas funciones forman las API web. La implementación interna es compleja y consiste principalmente en código C++. Las API nos proporcionan una interfaz que se puede invocar desde código Javascript.
Cuando invoca una función como setTimeout, Javascript entiende que se trata de una API web. Luego delega la ejecución de esta función al contenedor de API web. La función setTimeoutse ejecuta en un hilo separado. No se ejecuta en el hilo de ejecución de Javascript. Esta es la razón por la que el código escrito después setTimeoutse ejecuta antes de que se le pase la función de devolución de llamada.
Del mismo modo, dado que las llamadas de red toman tiempo, las funciones como fetchse ejecutan en un subproceso separado. Las API web del navegador nos ocultan la mayor parte de la complejidad. Por ejemplo: - la implementación interna de fetchcontendría formar una conexión TCP, enviar los datos y analizarlos. Además, también usaría los recursos informáticos de manera eficiente al programar la ejecución en el hilo apropiado.
El siguiente gif demuestra lo que sucede cuando ejecuta funciones de API web como setTimeout.
Como se vio anteriormente, una vez que se llama a la setTimeoutfunción, envía la función de devolución de llamada getActorsa las API web. En el contenedor de API web, la función setTimeoutespera cuatro segundos. Mientras tanto, getSubTitlesse llama a la función subsiguiente.
Ahora, puede preguntar cómo se getActorsejecuta la función de devolución de llamada después de que finaliza el temporizador. Veremos en la siguiente sección, cómo se ejecutan las devoluciones de llamada después de que regresan las API web.
Cola de eventos
Javascript depende en gran medida de las funciones de devolución de llamada. Las funciones de devolución de llamada se ejecutan una vez que ocurre un evento. Por ejemplo: - Después de recibir una respuesta del servidor, necesitamos imprimir la jsonrepresentación. O ejecute una función después de un retraso de 4 segundos.
El tiempo de ejecución de Javascript consta de un componente conocido como Cola de eventos o Cola de devolución de llamada. Es una cola de mensajes y utiliza el orden Primero en entrar, primero en salir (FIFO). Los mensajes no son más que funciones de devolución de llamada programadas para ejecutarse.
Pongamos un ejemplo para entender esto. En el siguiente código, estamos registrando una función de devolución de llamada cada vez que hay un evento de clic en un botón. Una vez que el usuario haga clic en el botón, onClickse llamará a la función. Esta función llama a la función timerdespués de un retraso de 2 segundos.
La animación anterior muestra lo que sucede detrás de escena. Aquí tenemos dos API web: a) $.onyb) setTimeout. La primera API espera a que se produzca un evento de clic. Una vez que recibe un evento de clic, ejecutará la función onClick. La segunda API setTimeOutes llamada posteriormente por la onClickfunción.
Cada vez que el usuario hace clic en el botón, la función onClickse inserta en la cola de eventos. De manera similar, después de que finaliza el temporizador, la función timerse coloca en la cola. Entonces, la cola de eventos se compone de todas las funciones de devolución de llamada que deben ejecutarse. En este caso, onClicky la timerfunción.
Bucle de eventos
Las funciones de devolución de llamada EventQueuellegan a la pila de ejecución de Javascript a través del bucle de eventos. El bucle de eventos comprueba continuamente si la pila de Javascript actual está vacía. Si encuentra que la pila está vacía, selecciona el primer mensaje de la Cola de eventos y lo pasa a la pila.
Tomando el ejemplo de la sección anterior, tan pronto como Event Loop encuentre que la pila está vacía, tomará el siguiente mensaje de la cola de devolución de llamada y lo ejecutará.
A continuación se muestra un pseudocódigo aproximado para el funcionamiento del bucle de eventos: -
Puede pensar en un bucle de eventos como un bucle infinito que supervisa continuamente la pila de ejecución. En caso de que la pila esté vacía, recogerá un mensaje (función) de la cola de eventos y lo ejecutará.
El siguiente diagrama muestra la representación de alto nivel del tiempo de ejecución de Javascript.
Hemos analizado los diferentes componentes en el tiempo de ejecución de Javascript. Ahora tendrá una mejor idea de cómo funciona Javascript bajo el capó. Resumamos lo que hemos aprendido hasta ahora.
Resumen
- Javascript tiene un solo subproceso y realiza una función a la vez.
- Aprovecha las API web para ejecutar tareas complejas en segundo plano.
- Una vez que se completa la ejecución de la API web, envía las funciones de devolución de llamada a la cola de eventos.
- El bucle de eventos comprueba continuamente si la pila de Javascript está vacía. En caso de que la pila esté vacía, selecciona la función de devolución de llamada de la cola de eventos y la ejecuta.
- Internos y tiempo de ejecución de Javascript
- Cómo funciona Javascript en el navegador y el nodo
- Una guía animada del bucle de eventos de Node.js
- ¿Qué diablos es el bucle de eventos de todos modos?
- Javascript asíncrono y bucle de eventos desde cero

![¿Qué es una lista vinculada, de todos modos? [Parte 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)



































