Así que JavaScript, como sabes, es un lenguaje de un solo hilo, lo que significa que solo puede ejecutar una cosa a la vez, y el código se ejecutará secuencialmente, ¿verdad? Así que cuando miras una pila de llamadas que tienes, las cosas se empujarán a esa pila, y luego tendrán que ir de arriba hacia abajo en lo que es su mecanismo de primero en entrar, primero en salir, ¿verdad? Y así, si miras un ejemplo, si tienes un montón de funciones que se llaman entre sí, la pila de llamadas se ve algo así. Así que tienes la ejecución principal, luego entras en la primera función, luego hay un console.log, así que podemos simplemente ejecutarlo inmediatamente. Lo sacaremos de la pila, luego empujaremos la segunda llamada allí. Luego entraremos en la segunda función, hay otro console.log. Podemos ejecutarlo inmediatamente, porque es como un nivel de hoja, así que nos desharemos de eso. Luego añadimos otra cosa a la pila de llamadas, porque queremos entrar en otra función, así que entraremos en la tercera, console.log eso, y luego podemos comenzar a sacar las cosas de la pila, porque hemos llegado al final de cada una de estas funciones. Así que uno por uno, pasaremos, nos desharemos de eso, y habremos terminado.
Y así, cuando ves que se lanza un error en algún lugar en JavaScript también, ahí es donde ese tipo de seguimiento de pila proviene. Te está diciendo dónde en la pila de llamadas de diferentes funciones que has llamado, de dónde básicamente se origina ese error si bajas por el árbol. Y como podrías haber visto con React Native a veces, si haces esto incorrectamente, puede ser bastante perjudicial. Así que puedes tener algún tipo de código roto aquí, que llama a A primero, luego llama a B, y B parece llamar a A de nuevo recursivamente, así que puedes simplemente seguir con esto, y luego terminarás viendo esto, ¿verdad? Todo es porque JavaScript es de un solo hilo. Es solo porque puede pasar por esta pila de llamadas y solo puede hacer una cosa a la vez, y si sigue pasando por ese proceso en un bucle, a veces puedes simplemente bloquear la pila de llamadas.
Así que entonces surge la pregunta, bueno, es de un solo hilo, ¿cómo hacemos estas tareas de larga duración como hacer llamadas de red o realizar un cálculo realmente pesado? Y ahí es donde entra el segundo componente de JavaScript, que es que es asíncrono, ¿verdad? Así que a pesar de ser de un solo hilo, JavaScript también es asíncrono, lo que significa que si quieres manejar operaciones como hacer llamadas de red o cosas que podrían bloquear una pila de llamadas, en realidad puedes hacerlo de forma asíncrona. Y ahí es donde entra en juego el bucle de eventos. Así que si tienes un setTimeout, que es un ejemplo básico de ejecutar una operación asíncrona con el bucle de eventos en proceso, si pasamos por el mismo proceso, tenemos la ejecución principal de todo el programa, luego haces un console.log para primero, luego llamas a un setTimeout. Ahora el setTimeout no va a hacer nada en la pila de llamadas. En su lugar, lo que hace es que va al tiempo de ejecución del navegador, y dice, básicamente empuja un temporizador allí, y se deshace de ese setTimeout de la pila de llamadas. Así que ahora está ejecutándose en algún lugar dentro del navegador, dentro del motor de JavaScript, y ya no está bloqueando la pila de llamadas.
Y así, el contenedor V8 o cualquiera que sea tu entorno, está a cargo de esperar a que ese temporizador suceda. Así que ejecuta algún código dentro de ese entorno para decir, espera aquí dos segundos. Mientras tanto, puedo ejecutar console.log segundo aquí. Así que entra en el siguiente, se deshace de eso. Y una vez que ese temporizador ha terminado, puede empujar esa devolución de llamada que le he proporcionado a la cola de devoluciones de llamada. Y ahí es donde entra en juego el bucle de eventos. Así que el bucle de eventos revisa la pila de llamadas y dice, ¿hay algo en la pila de llamadas que se esté ejecutando actualmente? Y si está vacía, lo que hará es mirar a través de la cola de devoluciones de llamada y empujar cosas hacia arriba en la pila de llamadas para ejecutar. Así que he empujado de nuevo mi función allí, la función tiene un console.log, lo ejecuta, y luego puede limpiar la pila de llamadas. Y así es como maneja el comportamiento asíncrono. Así que realmente el bucle de eventos de JS es muy simple. Lo que hace es revisar si hay algo en la cola de devoluciones de llamada. Y si la pila de llamadas está vacía, básicamente empuja todas las devoluciones de llamada en tu pila de llamadas y comienza a ejecutarlas.
Comments