2011-05-01 27 views
81

Supongo que una vez que se ejecuta, está en la cola, pero en la cola hay una garantía que invocará exactamente después de X milisegundos. ¿O otras tareas pesadas en la cola lo retrasarán?¿Cómo funciona setTimeout en Node.JS?

+11

Ningún sistema operativo que no sea en tiempo real podrá garantizar la precisión. Todo tipo de cosas en el sistema pueden (y lo harán) obstaculizar el mecanismo del temporizador. – Pointy

Respuesta

37

La idea de no bloquear es que las iteraciones de bucle son rápidas. Por lo tanto, para iterar para cada tick debería tomarse un tiempo suficientemente corto para que setTimeout sea preciso con una precisión razonable (aproximadamente < o más de 100 ms).

En teoría, tienes razón. Si escribo una aplicación y bloqueo el tic, se retrasará setTimeouts. Entonces, para responder a su pregunta, ¿quién puede asegurar que setTimeouts se ejecute a tiempo? Usted, al escribir un código que no sea de bloqueo, puede controlar el grado de precisión hasta casi cualquier grado razonable de precisión.

Siempre que javascript sea de "un único subproceso" en términos de ejecución de código (excluyendo web-workers y similares), eso siempre ocurrirá. La naturaleza de un único subproceso es una gran simplificación en la mayoría de los casos, pero requiere que el modismo no bloqueante sea exitoso.

Prueba este código a cabo ya sea en el navegador o en el nodo, y verá que no hay ninguna garantía de exactitud, por el contrario, el setTimeout será muy tarde:

var start = Date.now(); 

// expecting something close to 500 
setTimeout(function(){ console.log(Date.now() - start); }, 500); 

// fiddle with the number of iterations depending on how quick your machine is 
for(var i=0; i<5000000; ++i){} 

A menos que el intérprete optimiza el bucle de distancia (lo que no ocurre en Chrome), obtendrá algo entre miles. Retire el bucle y verá que es 500 en la nariz ...

6

La única forma de garantizar que se ejecuta el código es colocar la lógica de setTimeout en un proceso diferente.

Use el módulo de proceso hijo para generar un nuevo programa node.js que haga su lógica y pase datos a ese proceso a través de algún tipo de transmisión (tal vez tcp).

esta manera, incluso si algún código largo bloqueo se está ejecutando en el proceso principal de su proceso hijo ya ha comenzado en sí y se coloca un setTimeout en un nuevo proceso y un nuevo hilo y por lo tanto se ejecutará cuando se espera que lo haga.

Otras complicaciones se encuentran en un nivel de hardware en el que hay más subprocesos ejecutándose que los procesos y, por lo tanto, el cambio de contexto causará retrasos (muy pequeños) en el tiempo previsto. Esto debería ser insignificante y, si es importante, debe considerar seriamente lo que intenta hacer, por qué necesita tal precisión y qué tipo de hardware alternativo en tiempo real está disponible para hacer el trabajo.

En general, utilizar procesos secundarios y ejecutar aplicaciones de múltiples nodos como procesos separados junto con un equilibrador de carga o almacenamiento de datos compartido (como redis) es importante para escalar el código.

131

La semántica de setTimeout es más o menos la misma que en un navegador web: el tiempo de espera arg es mínimo número de ms a esperar antes de la ejecución, no es una garantía. Además, al pasar 0, un número no numérico o un número negativo, hará que espere un número mínimo de ms. En el nodo, esto es 1 ms, pero en los navegadores puede ser de hasta 50 ms.

La razón de esto es que no hay preferencia de JavaScript por JavaScript. Considere este ejemplo:

setTimeout(function() { 
    console.log('boo') 
}, 100) 
var end = Date.now() + 5000 
while (Date.now() < end) ; 
console.log('imma let you finish but blocking the event loop is the best bug of all TIME') 

El flujo aquí es:

  1. horario el tiempo de espera de 100 ms.
  2. busywait para 5000ms.
  3. volver al ciclo de eventos. verifica los temporizadores pendientes y ejecuta.

Si este no fue el caso, entonces podría tener un bit de JavaScript "interrumpir" el otro. Tendríamos que establecer exclusiones mutuas y semaphors y tal, para prevenir el código como el de ser extremadamente difícil de razonar acerca de:

var a = 100; 
setTimeout(function() { 
    a = 0; 
}, 0); 
var b = a; // 100 or 0? 

El single-threadedness de ejecución de JavaScript del Nodo hace que sea mucho más fácil de trabajar que la mayoría otros estilos de concurrencia. Por supuesto, la desventaja es que es posible que una parte del programa con mal comportamiento bloquee todo con un ciclo infinito.

¿Es este un mejor demonio de batalla que la complejidad de la apropiación? Eso depende.

+6

Obtiene un +1 por el mensaje 'console.log' excepcionalmente preciso. –

3

setTimeout es una especie de hilo , lleva a cabo una operación durante un tiempo determinado y ejecutar.

setTimeout(function,time_in_mills); 

aquí en primer argumento debe ser un tipo de función, Como aexample si desea imprimir usted nombra después de 3 segundos, el código debe ser algo llike a continuación.

setTimeout(function(){console.log('your name')},3000); 

poitn clave para recordar es decir, cualquier cosa que quiera hacer utilizando el método setTimeout , hazlo dentro de una función Si usted quiere llamar a algún otro método por parcing algunos parámetros, el código debe ser miradas como a continuación,

setTimeout(function(){yourOtherMethod(parameter);},3000); 

nodejs felices de codificación :)

3

setTimeout(callback,t) se utiliza para ejecutar devolución de llamada después de al menos t milisegundo. La demora real depende de muchos factores externos, como la granularidad del temporizador del sistema operativo y la carga del sistema.

Por lo tanto, existe la posibilidad de que se invoque un poco después de la hora establecida, pero nunca se invocará antes.

Un temporizador no puede abarcar más de 24.8 días.