node.js

¿Cómo creo una función asíncrona no bloqueante en node.js?



(9)

¿Cómo creo una función asíncrona sin bloqueo? A continuación se muestra lo que estoy tratando de lograr, pero mi programa sigue bloqueando ...

var sys = require("sys"); function doSomething() { sys.puts("why does this block?"); while(true); } setTimeout(doSomething,0); setTimeout(doSomething,0); setTimeout(doSomething,0); sys.puts("main");


Cruzada desde Reddit .

El propósito de las funciones asíncronas en JavaScript es un poco diferente de lo que buscas.

Recuerde que JavaScript es de un solo hilo, solo puede hacer una cosa a la vez. Aquí hay un código de bloqueo tradicional:

sys.puts("Before"); sleep(10); sys.puts("After");

En una aplicación web del mundo real, el sleep() podría ser, en cambio, una llamada de base de datos, una solicitud de red (como esperar datos del navegador web del usuario), una herramienta auxiliar o acceso a archivos.

Si utilizó llamadas de bloqueo como las anteriores, el servidor Node.js no podría hacer nada más (como comenzar a manejar otras solicitudes web) mientras espera.

PHP y muchos otros entornos de programación web manejan esto creando subprocesos totalmente separados para cada solicitud. Node.js utiliza funciones de devolución de llamada. Podrías escribir el mismo código así, en su lugar:

sys.puts("Before"); setTimeout(function(){ sys.puts("After"); }, 10000);

Aquí, creas una función y la pasas a setTimeout() . Su código aún no se ha ejecutado, pero cuando lo haga, tendrá acceso a todos los ámbitos (todas las variables) donde se creó. setTimeout() obtiene una referencia a la función y programa un evento para que se active en el bucle de eventos después de que expire el tiempo de espera.

El bucle de eventos es, esencialmente, la lista de tareas del programa Node.js (son comunes: todas las aplicaciones GUI que se ejecutan en su computadora probablemente usan bucles de eventos).

Después de la llamada a setTimeout() , la función actual sigue ejecutándose. Eventualmente regresa, y la función que lo llamó regresa, y así sucesivamente, hasta que el programa termina nuevamente en el bucle de eventos. El bucle de eventos mira si algo sucedió (por ejemplo, una solicitud entrante) mientras se estaba ejecutando su código, y llama a la función apropiada en su código. Si no, espera hasta que algo suceda (como el tiempo de espera que expira).

El código asíncrono no permite que su código haga muchas cosas al mismo tiempo, elimina el bloqueo cuando algún código depende de algo externo para continuar.

Es raro que necesite realizar un trabajo de bloqueo dentro de su programa Node.js. Si lo hace, debe separar ese trabajo en un proceso separado (que incluso puede ser otro programa Node.js), o escribir un complemento C / C ++ que sea libre de usar hilos.


Esta línea:

while(true);

no es "bloquear", solo está ocupado, para siempre.



Puede hacer esto sin usar un proceso secundario usando nextTick ()

Acabo de leer esta explicación el otro día sobre nextTick ... es una gran lectura, OMI.

--- editar: antiguo enlace está muerto. Encontró uno nuevo a la derecha en

entendiendo la cola de eventos node.js y process.nextTick


Si entiendo lo que está buscando, tiene dos funciones (ambas aceptan una devolución de llamada como argumento):

process.nextTick : esta función se puede apilar, lo que significa que si se llama recursivamente, generará un gran número de veces ( process.maxTickDepth ) por tic del bucle de eventos.

o

setImmediate : esta función está mucho más cerca de establecer un tiempo de espera de 0 (pero sucede antes).

En la mayoría de los casos, debería preferir setImmediate.


Si no desea utilizar la API de WebWorker / node-worker, que todavía es muy alfa, simplemente cree un programa de nodo adicional y comuníquese a través de TCP o HTTP.

Esto le permite enviar su trabajo como llamadas HTTP o datos TCP sin procesar y esperar asincrónicamente la respuesta HTTP / respuesta TCP entrante.

Sin embargo, tenga en cuenta que esto solo es apropiado si su tarea es fácilmente serializable.


Solo puede hacer E / S asíncronas en node.js utilizando las funciones de E / S asíncronas proporcionadas por las extensiones de node.js runtime o node.js escritas en C ++. Su propio código Javascript siempre está sincronizado en node.js. Rara vez se necesita un código asíncrono no IO, y los diseñadores de node.js decidieron evitarlo en absoluto.

Hay algunas formas erróneas de ejecutar Javascript asincrónicamente en node.js, mencionadas por otros comentaristas, pero node.js no está diseñado para este tipo de trabajo. Use Erlang si necesita ese tipo de concurrencia, node.js solo trata sobre la E / S paralela, y para los cálculos en paralelo es tan malo como Python o PHP.


Supongo que también está experimentando con Nodejs. Supongo que no está escribiendo ningún módulo npm y exportando su función como función asíncrona. En la práctica, no encontrará este caso, si desea realizar alguna operación de bloqueo en las funciones o en las devoluciones de llamadas que se ejecutan en un solo entorno de subprocesos, intente usar módulos de nodos apropiados como fs para la lectura de archivos, solicitud de red y módulo asíncrono que proporciona varios tipos de operaciones asíncronas, también recuerde que está intentando ejecutar código de consumo de CPU de forma asíncrona Es una mala idea, porque 2HZ puede ejecutar un millón de líneas de código en menos de microsegundos

El propósito principal de nodejs es resolver el problema que ha planteado en la pregunta que es manejada por el libuv subyacente para manejar eventos asíncronos, agradezco la respuesta de usar el tiempo de espera establecido, pero no sabe cuánto tiempo esperar o esperar. el uso de node worker está bien, pero terminará escribiendo un montón de código de placa de caldera, así que simplemente busque el módulo npm que satisfaga sus necesidades.


setTimeout no creará un nuevo hilo, por lo que el navegador seguirá colgando en el bucle infinito.

Necesitas repensar la estructura de tu programa.