while mdn infinito for eventos event ejemplos ciclo bucle javascript multithreading node.js asynchronous event-loop

infinito - eventos javascript mdn



Comprender el bucle de eventos (3)

1: Si hablamos de una aplicación de subproceso único, ¿qué procesos establece SetTimeouts mientras el motor JS acepta más solicitudes y las ejecuta? ¿No es ese solo hilo continuará trabajando en otras solicitudes? Entonces, ¿quién va a seguir trabajando en setTimeout mientras otras solicitudes siguen llegando y se ejecutan?

Solo hay 1 subproceso en el proceso de nodo que realmente ejecutará el JavaScript de su programa. Sin embargo, dentro del nodo, en realidad hay varios hilos que manejan la operación del mecanismo de bucle de eventos, y esto incluye un conjunto de hilos de E / S y un puñado de otros. La clave es que el número de estos subprocesos no corresponde al número de conexiones simultáneas que se manejan como lo harían en un modelo de concurrencia de subprocesos por conexión.

Ahora, acerca de "ejecutar setTimeouts", cuando setTimeout , todo lo que hace el nodo es básicamente actualizar una estructura de datos de las funciones que se ejecutarán a la vez en el futuro. Básicamente tiene un montón de cosas que necesita hacer y cada "tic" del ciclo de eventos selecciona uno, lo elimina de la cola y lo ejecuta.

Una cosa clave para entender es que el nodo depende del sistema operativo para la mayoría del trabajo pesado. El sistema operativo realmente rastrea las solicitudes de red entrantes y, cuando el nodo está listo para manejar una, solo utiliza una llamada al sistema para solicitar al sistema operativo una solicitud de red con los datos listos para ser procesados. Gran parte del nodo "trabajo" IO es "Hey OS, ¿tiene una conexión de red con datos listos para leer?" o "Hola OS, ¿alguna de mis llamadas destacadas del sistema de archivos tiene datos listos?". En función de su algoritmo interno y el diseño del motor de bucle de eventos, el nodo seleccionará un "tic" de JavaScript para ejecutarlo, lo ejecutará y luego repetirá el proceso una vez más. Eso es lo que significa el ciclo de eventos. El nodo básicamente, en todo momento, determina "¿cuál es el próximo poco de JavaScript que debería ejecutar?" Y luego lo ejecuta. Estos factores en los cuales IO ha completado el sistema operativo, y cosas que han sido puestas en cola en JavaScript a través de llamadas a setTimeout o process.nextTick .

2: Si estos setTimeout se ejecutarán detrás de las escenas mientras más solicitudes están entrando y entrando y se están ejecutando, la cosa que lleva a cabo las ejecuciones asincrónicas detrás de las escenas es de la que estamos hablando EventLoop?

No se ejecuta JavaScript entre bastidores. Todo el JavaScript en su programa se ejecuta al frente y al centro, uno a la vez. Lo que ocurre detrás de las escenas es que el SO maneja IO y el nodo espera que esté listo y el nodo maneja su cola de javascript esperando para ejecutarse.

3: ¿Cómo puede saber JS Engine si se trata de una función asíncrona para que pueda colocarlo en EventLoop?

Hay un conjunto fijo de funciones en el núcleo del nodo que son asíncronas porque hacen llamadas al sistema y el nodo sabe cuáles son porque tienen que llamar al sistema operativo o C ++. Básicamente todas las IO de redes y sistemas de archivos, así como las interacciones de procesos secundarios serán asíncronas y la ÚNICA forma en que JavaScript puede hacer que un nodo ejecute algo de forma asíncrona es invocando una de las funciones asíncronas proporcionadas por la biblioteca central del nodo. Incluso si está usando un paquete npm que define su propia API, para producir el bucle de evento, eventualmente el código del paquete npm llamará a una de las funciones asincrónicas del núcleo del nodo y es entonces cuando el nodo sabe que la marca está completa y puede iniciar el evento algoritmo de bucle de nuevo.

4 The Event Loop es una cola de funciones de devolución de llamada. Cuando se ejecuta una función asíncrona, la función de devolución de llamada se inserta en la cola. El motor JavaScript no comienza a procesar el bucle de evento hasta que se ejecuta el código después de que se haya ejecutado una función asíncrona.

Sí, esto es cierto, pero es engañoso. La clave es que el patrón normal es:

//Let''s say this code is running in tick 1 fs.readFile("/home/barney/colors.txt", function (error, data) { //The code inside this callback function will absolutely NOT run in tick 1 //It will run in some tick >= 2 }); //This code will absolutely also run in tick 1 //HOWEVER, typically there''s not much else to do here, //so at some point soon after queueing up some async IO, this tick //will have nothing useful to do so it will just end because the IO result //is necessary before anything useful can be done

Así que sí, puedes bloquear totalmente el ciclo de eventos contando los números de Fibonacci sincrónicamente todos en la memoria, todo en el mismo tic, y eso congelaría tu programa. Es concurrencia cooperativa. Cada tilde de JavaScript debe generar el bucle de evento dentro de un período de tiempo razonable o la arquitectura general falla.

Estoy pensando en esto y esto es lo que se me ocurrió:

Digamos que tenemos un código como este:

console.clear(); console.log("a"); setTimeout(function(){console.log("b");},1000); console.log("c"); setTimeout(function(){console.log("d");},0);

Se recibe una solicitud y el motor JS comienza a ejecutar el código anterior paso a paso. Las dos primeras llamadas son llamadas de sincronización. Pero cuando se trata del método setTimeout , se convierte en una ejecución asíncrona. Pero JS inmediatamente regresa de él y continúa la ejecución, que se llama Non-Blocking o Async . Y continúa trabajando en otros, etc.

Los resultados de esta ejecución son los siguientes:

acdb

Así que, básicamente, el segundo setTimeout se terminó primero y su función de devolución de llamada se ejecuta antes que la primera y eso tiene sentido.

Estamos hablando de una aplicación de subproceso único aquí. JS Engine sigue ejecutando esto y, a menos que finalice la primera solicitud, no pasará a la segunda. Pero lo bueno es que no esperará a que se resuelvan las operaciones de bloqueo como setTimeout por lo que será más rápido porque acepta las nuevas solicitudes entrantes.

Pero mis preguntas surgen en torno a los siguientes elementos:

# 1: Si hablamos de una aplicación de un único subproceso, ¿qué mecanismo procesa setTimeouts mientras el motor JS acepta más solicitudes y las ejecuta? ¿Cómo continúa el hilo único trabajando en otras solicitudes? Lo que funciona en setTimeout mientras otras solicitudes siguen llegando y se ejecutan.

# 2: Si estas funciones setTimeout se ejecutan detrás de escena mientras más solicitudes entran y se están ejecutando, ¿qué lleva a cabo las ejecuciones asincrónicas entre bastidores? ¿Qué es esto de lo que hablamos llamado EventLoop ?

# 3: ¿ Pero no debería ponerse todo el método en EventLoop para que se ejecute todo y se llame al método de devolución de llamada? Esto es lo que entiendo cuando hablo de funciones de devolución de llamada:

function downloadFile(filePath, callback) { blah.downloadFile(filePath); callback(); }

Pero en este caso, ¿cómo sabe el motor JS si se trata de una función asíncrona para que pueda poner la devolución de llamada en el EventLoop? Perhaps something like the EventLoop? Perhaps something like the palabra clave async` en C # o algún tipo de atributo que indique el método que asumirá JS Engine es un método asíncrono y debe tratarse en consecuencia.

# 4: Pero un article dice bastante contrario a lo que estaba adivinando sobre cómo las cosas podrían estar funcionando:

El bucle de evento es una cola de funciones de devolución de llamada. Cuando se ejecuta una función asíncrona, la función de devolución de llamada se inserta en la cola. El motor JavaScript no comienza a procesar el bucle de evento hasta que se ejecuta el código después de que se haya ejecutado una función asíncrona.

# 5: Y hay una imagen aquí que podría ser útil, pero la primera explicación en la imagen es decir exactamente lo mismo que se menciona en la pregunta número 4:

¿Entonces mi pregunta aquí es obtener algunas aclaraciones sobre los artículos enumerados arriba?


Existe un video tutorial fantástico de Philip Roberts, que explica el ciclo de eventos de JavaScript de la manera más simple y conceptual. Todos los desarrolladores de javascript deberían echarle un vistazo.

Aquí está el link del video en Youtube.


No crea que el proceso de host sea de subproceso único, no lo son. Lo que es single-threaded es la parte del proceso de host que ejecuta su código de JavaScript.

Excepto por los trabajadores de base , pero estos complican el escenario ...

Por lo tanto, todos los códigos js se ejecutan en el mismo subproceso, y no hay posibilidad de que obtenga dos partes diferentes de su código js para que se ejecuten al mismo tiempo (por lo tanto, no obtendrá concurrencia nigthmare para administrar).

El código js que se está ejecutando es el último código que el proceso del host recogió del bucle de evento. En su código, básicamente puede hacer dos cosas: ejecutar instrucciones sincrónicas y programar las funciones que se ejecutarán en el futuro cuando ocurran algunos eventos.

Aquí está mi representación mental (cuidado: es solo eso, ¡no conozco los detalles de implementación del navegador!) De su código de ejemplo:

console.clear(); //exec sync console.log("a"); //exec sync setTimeout( //schedule inAWhile to be executed at now +1 s function inAWhile(){ console.log("b"); },1000); console.log("c"); //exec sync setTimeout( function justNow(){ //schedule justNow to be executed just now console.log("d"); },0);

Mientras su código se está ejecutando, otro hilo en el proceso de host realiza un seguimiento de todos los eventos del sistema que están ocurriendo (clics en la interfaz de usuario, archivos leídos, paquetes de redes recibidos, etc.)

Cuando se completa el código, se elimina del bucle de evento y el proceso de host vuelve a verificarlo para ver si hay más código para ejecutar. El bucle de eventos contiene dos manejadores de eventos más: uno para ser ejecutado ahora (la función justNow) y otro dentro de un segundo (la función inAWhile).

El proceso de host ahora intenta hacer coincidir todos los eventos para ver si hay controladores registrados para ellos. Descubrió que el evento que Just Now está esperando ha sucedido, por lo que comienza a ejecutar su código. Cuando acaba de salir la función JustNow, verifica el bucle de evento en otro momento, buscando controladores para los eventos. Suponiendo que ha transcurrido 1 s, ejecuta la función inAWhile, y así sucesivamente ....