Hamburger Icon
Destripando JavaScript - Parte 2

Destripando JavaScript - Parte 2

En el artículo anterior vimos por encima la historia de JavaScript y qué hacen los navegadores para interpretarlo. Ahora, vamos a ver cómo funciona JavaScript en tiempo de ejecución.

Vamos a ver que en JavaScript, todo y tener un solo hilo de ejecución, permite que hagamos algunas tareas en segundo plano (o al menos, que nos lo parezca), veremos cómo usa la memoria y la pila. Entenderemos qué son el loop de eventos y la cola de llamadas.

Si te dedicas a desarrollar con JavaScript, entender todo esto te ayudará a desarrollar mejores aplicaciones y posteriormente a entender qué está pasando en estas cuando no funcionen correctamente.

Un solo hilo de ejecución

A diferencia de otros lenguajes, en JavaScript solo tenemos un hilo de ejecución. Esto quiere decir que JavaScript no puede hacer ninguna tarea en paralelo.

Todo el código se ejecuta de forma secuencial, de modo que si hay algo que tarda más de la cuenta en ejecutarse, el resto de código tendrá que esperar para ser ejecutado. Prueba a poner en un archivo este código y ejecútalo, verás como en unos minutos el Navegador te avisará de que algo va mal y podrás terminar la ejecución:

console.log("primer mensaje")

while (1 === 1) {
  // no pasaremos de aquí
}

console.log("segundo mensaje")

Cuando usas tu navegador preferido, habitualmente cada pestaña es gestionada por un hilo de ejecución, que a parte de ejecutar JavaScript se encarga de absolutamente todo lo que hagas en el navegador, desde subir y bajar por la página hasta hacer clic en botones. Todo.

Si la ejecución se bloquea como en el ejemplo anterior, no podrás hacer nada, la pestaña no te va a responder.

Componentes en la ejecución de JavaScript

Los componentes principales son estos:

Pila de llamadas: es una estructura LIFO (Last In First Out), el último en entrar es el primero en salir. Imagina que guardas los platos apilados uno encima de otro, cuando necesites coger uno cogerás el primero, el de arriba, que es el último que guardaste.

Esta estructura se encarga de gestionar el contexto de ejecución de cada momento. Si llamamos a una función, el contexto de esa función se pone en la pila y ahí se queda hasta que la función termina. Si antes de que termine una función hacemos más llamadas a otras funciones, se pondran encima de la pila en el orden correspondiente.

Cola de mensajes o callbacks: es una estructura FIFO (First In First Out), el primero en entrar será el primero en salir.

Cuando hacemos peticiones HTTP con fetch, configuramos eventos en el DOM, usamos el almacenamiento local u otras operaciones asíncronas, realmente no es JavaScript el encargado de llevarlas a cabo, sino el navegador. El navegador pone a nuestra disposición una API que usamos a través de JavaScript y en la que solemos indicar una función callback o de retorno. El navegador es el encargado de aplicar la lógica para llevar a cabo estas tareas de forma independiente al hilo de ejecución de JavaScript.

Esto es así para que el navegador pueda ejecutar ciertas tareas en un hilo de ejecución a parte, sin que JavaScript sepa nada de este. Cuando el navegador termina de ejecutar una de estas tareas asíncronas, pone en la cola de callbacks el resultado con la función callback que hemos indicado antes. Es una forma de devolverle a JavaScript el control de la ejecución de esa parte de la lógica.

Loop de eventos: mira constantemente la cola de callbacks y, cuando hay algo ahí, se espera a que la pila de llamadas esté vacía y entonces hace un push en la pila de llamadas, para que JavaScript ejecute esa función.

Memoria: espacio donde se almacenan todas las variables y su valor. JavaScript tiene un garbage collector que se encarga de hacer limpieza de los datos que la aplicación ya no necesita.

Es más fácil entender todo esto de forma visual. Mira este código:

function holaMundo() {
  console.log("Hola mundo")
}

function tercera() {
  setTimeout(holaMundo, 3000)
}

function segunda() {
  tercera()
}

function primera() {
  segunda()
}

primera()

Básicamente tenemos una primera función que llama a una segunda, esta segunda llama a una tercera y esta tercera usa la función setTimeout para ejecutar la función holaMundo una vez pasan tres segundos. Esto es lo que ocurre:

https://a.storyblok.com/f/96536/1488x792/fe22b75b09/destripando-javascript-ejemplo.gif

Si quieres probarlo tú, puedes hacerlo desde esta aplicación web.

A grandes rasgos, así es como funciona JavaScript.