javascript - son - promise nodejs
Hilos ocultos en JavaScript/Node que nunca ejecutan código de usuario: ¿es posible, y si es así podría llevar a una posibilidad arcana para una condición de carrera? (3)
Ver la parte inferior de la pregunta para una actualización, basada en comentarios / respuestas: esta pregunta es realmente acerca de la posibilidad de hilos ocultos que no ejecutan devoluciones de llamada.
Tengo una pregunta sobre un escenario arcano potencial que involucra el módulo de solicitud de nodo en el que:
Se construye y ejecuta una solicitud HTTP completa a través de la red (tomando sin embargo muchos ms o incluso segundos)
... antes de que se ejecute una sola función en el tiempo de ejecución en la máquina local (típicamente en nanosegundos?) - ver a continuación para obtener más detalles
Estoy publicando esto principalmente como un cheque de cordura solo para asegurarme de no estar malinterpretando algo sobre el código del módulo Node / JS / Request.
De los ejemplos en el módulo de Solicitud (vea el SEGUNDO ejemplo en esa sección), está esto:
// Copied-and-pasted from the second example in the
// Node Request library documentation, here:
// https://www.npmjs.com/package/request#examples
// ... My ARCANE SCENARIO is injected in the middle
var request = require(''request'')
request(
{ method: ''GET''
, uri: ''http://www.google.com''
, gzip: true
}
, function (error, response, body) {
// body is the decompressed response body
console.log(''server encoded the data as: '' + (response.headers[''content-encoding''] || ''identity''))
console.log(''the decoded data is: '' + body)
}
)
// **************************************************** //
// Is the following scenario possible?
//
// <-- HANG HANG HANG HANG HANG HANG HANG HANG HANG -->
//
// Let us pretend that the current thread HANGS here,
// but that the request had time to be sent,
// and the response is pending being received by the thread
//
// <-- HANG HANG HANG HANG HANG HANG HANG HANG HANG -->
// **************************************************** //
.on(''data'', function(data) {
// decompressed data as it is received
console.log(''decoded chunk: '' + data)
})
.on(''response'', function(response) {
// unmodified http.IncomingMessage object
response.on(''data'', function(data) {
// compressed data as it is received
console.log(''received '' + data.length + '' bytes of compressed data'')
})
})
He indicado mi situación arcana en el fragmento de código.
Supongamos que el proceso Nodo se cuelga en el punto indicado, pero ese Nodo internamente (en un hilo oculto , invisible para Javascript y, por lo tanto, no llama a ninguna devolución de llamada) FUE capaz de construir la solicitud y enviarla a través de la red; supongamos que el bloqueo continúa hasta que se recibe una respuesta (en dos partes, por ejemplo) y está esperando a ser procesada por Nodo. (Este es el escenario que es ciertamente arcano, y que no estoy seguro es incluso teóricamente posible).
Entonces supongamos que el hang termina y el hilo del nodo anterior se despierta. Además, supongamos que (de alguna manera) Node pudo procesar la respuesta hasta el punto de ejecutar la función de devolución de llamada en el código anterior (pero sin pasar el punto "colgado" en el código en la ruta del código original - nuevamente , si esto es incluso teóricamente posible).
¿El escenario arcano anterior es teóricamente posible? Si es así, ¿no se recibirían los paquetes de datos por la red y se combinarían, listos para pasar a la función de devolución de llamada, antes de que el evento ''data''
se programara en el objeto? En este caso, si es posible, me imagino que el evento ''data''
se perderá.
Nuevamente, entiendo que este es un escenario arcano, quizás ni siquiera sea teóricamente posible, dados los mecanismos internos y la codificación involucrados.
Esa es mi pregunta: ¿es el escenario arcaico anterior, con su condición de raza extremadamente improbable, no obstante teóricamente posible?
Solo pregunto para asegurarme de que no me falta ningún punto clave. Gracias.
ACTUALIZACIÓN : De comentarios y respuestas: ahora he aclarado mi pregunta. El ''escenario arcano'' requeriría que haya un hilo OCULTO (que por lo tanto NO PUEDE ejecutar ningún código de USUARIO, incluyendo CALLBACKS) que construye la solicitud, la envía a través de la red y recibe la respuesta SIN que se activen devoluciones de llamada, incluyendo el Devolución ''data''
llamada de ''data''
- y se detiene justo en el punto en que la devolución ''response''
llamada de ''response''
está lista para ser llamada, esperando a que se active el hilo JS (único) visible.
No, esto no puede suceder.
Sí, de hecho hay subprocesos de fondo "ocultos" que hacen el trabajo para los métodos asíncronos, pero que no llaman a las devoluciones de llamada . Toda ejecución de javascript ocurre en el mismo hilo, sincrónicamente, secuencialmente. Esa devolución de llamada de evento de data
siempre se ejecutará de forma asíncrona , es decir, después de que la secuencia de comandos / función actual se haya completado.
Si bien es posible que ya lleguen paquetes desde la red antes de que se cree la devolución de llamada y se adjunte al emisor del evento, la devolución de llamada que escucha paquetes en el nivel más bajo siempre se crea antes de que se envíe la solicitud; es un argumento del "makeRequest" nativo "método, y está disponible para ser llamado desde el principio. Entonces, cuando un paquete llega antes de que el script actual (aún ocupado por la construcción de los emisores de eventos y los controladores adjuntos) haya finalizado, este evento se pone en cola y la devolución de llamada solo se ejecutará después de que el ciclo de eventos esté listo, en el siguiente turno. Para entonces, la devolución de llamada del evento de data
ciertamente se crea y se adjunta.
Solo hay un hilo involucrado en Node.js; un bucle de eventos se utiliza para procesar tareas que se ejecutan de forma asincrónica, y nada en cola puede interrumpir algo que ya se esté ejecutando. Entonces no, no hay una condición de carrera allí.
la ejecución de nodejs Javsacript tiene un único hilo y es controlada por eventos. Eso significa que todo se ejecuta a través de una cola de eventos. Se ejecuta un hilo de ejecución de Javascript hasta que finaliza y luego el sistema verifica la cola de eventos para ver si hay algo más que hacer (temporizadores esperando disparar, sincronizar devoluciones de llamada que esperan ser llamados, etc.).
nodejs utiliza algunos subprocesos internos en algunas de sus implementaciones (como la E / S de archivos), pero entiendo que no utiliza subprocesos en las redes. Pero no importa si hay algunos subprocesos internos o no, porque todas las comunicaciones entre subsistemas, como las redes y el hilo JS del nodo principal, se realizan a través de la cola de eventos.
El hilo de ejecución de un nodej nunca se interrumpe para hacer otra cosa. Termina y finaliza, luego el motor JS comprueba la cola de eventos para ver si hay algo más esperando para ejecutarse.
Cuando hay datos entrantes disponibles en el socket, se coloca un evento en la cola del evento. El nodo actual Javascript que se está ejecutando termina de hacer lo que está haciendo, entonces el motor JS ve que hay un evento en la cola de eventos y dispara ese evento. Si hay una devolución de llamada de función o controlador de evento asociado con ese evento (normalmente lo hay), se llama a ese para ejecutar el evento.
Si hay un error en el funcionamiento interno de alguna infraestructura, como las redes, entonces todo lo que sucede con el código del nodo es que algunos eventos de red simplemente no ocurren. El código nodejs tiene sus controladores de eventos en su lugar y simplemente no recibe el evento que están esperando hasta que la infraestructura se libere y cree el evento. Esto no crea ningún tipo de bloqueo en el código del nodojs.
Entonces, en tu actualización:
De comentarios y respuestas: ahora he aclarado mi pregunta. El ''escenario arcano'' requeriría que haya un hilo OCULTO (que por lo tanto NO PUEDE ejecutar ningún código de USUARIO, incluyendo CALLBACKS) que construye la solicitud, la envía a través de la red y recibe la respuesta SIN que se activen devoluciones de llamada, incluyendo el Devolución de llamada de ''datos'' - y se detiene justo en el punto en que la devolución de llamada de ''respuesta'' está lista para ser llamada, esperando a que se active el hilo JS (único) visible.
El subproceso nodejs se ejecuta hasta su finalización, luego el motor JS espera que ocurra un nuevo evento (por ejemplo, poner en la cola de eventos). Cuando ocurre ese evento, el motor JS ejecuta el código que corresponde a ese evento (controladores de eventos, devoluciones de llamadas, etc.). Haces que parezca que el único hilo JS visible está dormido esperando a que se despierte y puede quedarse atorado allí porque otro subsistema se cuelga. Ese no es el caso. Lo único que puede suceder es que nunca se produzca algún evento por el que el hilo JS único tenga un controlador de eventos. Esto no sería diferente de una situación en la que envía un mensaje a un servidor y tiene un controlador de eventos para ver una respuesta, pero el servidor nunca envía la respuesta. El código de su nodo continúa procesando otros eventos (temporizadores, otras redes, otras E / S), pero este evento en particular nunca ocurre porque el otro servidor nunca envió los datos que desencadenarían ese evento. Nada se bloquea
Esto es "e / Evented Eve", que es cómo nodejs se describe a sí mismo.