2010-05-20 14 views
21

¿Cómo creo una función asíncrona sin bloqueo? A continuación es lo que estoy tratando de lograr, pero mi programa sigue bloqueando ...¿Cómo creo una función asincrónica sin bloqueo en node.js?

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"); 

Respuesta

3

setTimeout no va a crear un nuevo hilo, por lo que el navegador todavía se colgará en el bucle infinito.

Necesita replantear la estructura de su programa.

+0

¿Tiene alguna idea de cómo logro esto en node.js? Gracias – Richard

+1

Esta pregunta es bastante antigua, pero sigue siendo muy interesante para los principiantes de node.js como yo .. Como se mencionó, node.js es para E/S paralelas que no funcionan en paralelo. Eso significa que: si tiene que realizar un trabajo lento para responder a un solo nodo de solicitud, no acelerará lo que intenta lograr en esa única solicitud. La diferencia entre usar sleep() y setTimeout() es que node.js bloqueará todas las demás solicitudes cuando use sleep() durante el tiempo de inactividad - usar setTimeout() no bloqueará otras solicitudes. O bien, 10 solicitudes para dormir (10s) tomarán 100s: 10 solicitudes para establecer TimeTimeout (10s) solo 10s. – schlicki

10

Necesita ejecutar su función de bloqueo en un proceso separado.

Este módulo puede ayudar: http://github.com/cramforce/node-worker

+26

Es importante comprender que ese nodo no se trata de funciones que son asincrónicas todo el tiempo. Se trata de que * i/o * sea asincrónico y no bloqueante. Si su función no hace ninguna entrada/salida, el nodo no lo ayudará a hacerlo asíncrono. Sin embargo, proporciona herramientas que le permitirán hacer eso. Al igual que los procesos secundarios. Esa es la respuesta de Felix. Su función puede engendrar un proceso hijo para hacer su trabajo y se ejecutará fuera del ciclo del evento principal. – Marco

-6

Esta línea:

while(true); 

no es "bloqueo", es sólo ocupado, siempre.

4

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

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

Nota, sin embargo, esto solo es apropiado si su tarea es fácilmente serializable.

11

Solo puede hacer IO asincrónico en node.js utilizando las funciones IO asíncronas proporcionadas por las extensiones node.js runtime o node.js escritas en C++. Tu propio código Javascript siempre es sincrónico en node.js. El código asincrónico no IO raramente es necesario, y los diseñadores de node.js decidieron evitarlo en absoluto.

Existen algunas formas misteriosas de ejecutar Javascript de forma asincrónica en node.js, mencionadas por otros comentaristas, pero node.js no está diseñado para este tipo de trabajo. Utilice Erlang si necesita ese tipo de concurrencia, node.js solo se trata de IO paralela, y para cálculos paralelos es tan malo como Python o PHP.

+0

Gran respuesta, tengo una pregunta: ¿La operación mongo db en Node.js es IO asíncrona? –

+1

Sí. '.connect' y' .insert', por ejemplo, son funciones asíncronas. Ver http://mongodb.github.io/node-mongodb-native/2.0/overview/quickstart/ – nponeccop

31

Publicación cruzada desde Reddit.


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

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

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

En una aplicación web en el mundo real, el sleep() podría ser en cambio un tiempo de llamada base de datos, solicitud de red (como la espera de los datos desde el navegador web del usuario), ayudante herramienta, o acceso a archivos.

Si usó llamadas de bloqueo como las anteriores, el servidor Node.js no podría hacer nada más (como comenzar a gestionar 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 usa funciones de devolución de llamada.Se puede escribir el mismo código como este, en su lugar:

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

Aquí, se crea una función y lo pasa a setTimeout(). Su código aún no se ha ejecutado, pero cuando lo haga, tendrá acceso a todo el alcance (todas las variables) donde fue creado. setTimeout() obtiene una referencia a la función y programa un evento para disparar en the event loop una vez que expira el tiempo de espera.

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

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

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

Es raro que deba 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 escriba a C/C++ addon, que es libre de usar subprocesos.

+1

¡Ah! Ahora lo entiendo más claramente. Gracias por la explicación; su tercer párrafo fue especialmente útil. +1 –

2

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

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

o

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

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

0

Supongo que está experimentando con Nodejs, también estoy asumiendo que no está escribiendo ningún módulo npm y exportando su función como función asincrónica. En la práctica, no encontrará este caso, si desea realizar alguna operación de bloqueo en las funciones o en las devoluciones de llamada que se ejecutan en un entorno de subproceso único, intente utilizar módulos de nodo apropiados como fs para lectura de archivos, solicitud de solicitud de red y módulo asíncrono que proporciona varios tipos de operaciones asincrónicas, también recuerde que está intentando ejecutar CPU consume código asincrónicamente es una mala idea, porque 2HZ puede ejecutar un millón de líneas de código en menos de microsegundos

El objetivo principal de nodejs es resolver el problema que ha planteado en la pregunta que es manejado por la libuv subyacente para manejar eventos asincrónicos, agradezco la respuesta de usar el tiempo de espera configurado, pero no sabe cuánto tiempo esperar o usar el nodo trabajador está bien, pero terminará escribiendo mucho código de placa de caldera, por lo simplemente busque el módulo npm que satisfaga su necesidad.

Cuestiones relacionadas