Pregunta ¿Por qué no setTimeout cancela mi ciclo?


Me preguntaba cuántas veces puede un JavaScript while La declaración (en la consola de Chrome) puede incrementar una variable en milisegundos, así que rápidamente escribí este fragmento directamente en la consola:

var run = true, i = 0;
setTimeout(function(){ run = false; }, 1);
while(run){ i++; }

El problema es que funciona para siempre.
¿Por qué sucede esto y cómo puedo resolverlo?


75
2018-02-09 08:04


origen


Respuestas:


Esto vuelve a la naturaleza de un solo subproceso de JavaScript1. Lo que sucede es más o menos esto:

  1. Tus variables están asignadas.
  2. Usted programa una función, para establecer run = false. Esto está programado para ser ejecutado después la función actual se ejecuta (o cualquier otra cosa que esté actualmente activa).
  3. Usted tiene su ciclo infinito y permanece dentro de la función actual.
  4. Después de su ciclo infinito (Nunca), el setTimeout() la devolución de llamada se ejecutará y run=false.

Como puedes ver, un setTimeout() enfoque no funcionará aquí. Puede solucionarlo comprobando el tiempo en el while condición, pero esto alterará su medición real.

1 Al menos para fines más prácticos, puede verlo como un único subproceso. En realidad hay un llamado "evento-loop". En ese bucle, todas las funciones se ponen en cola hasta que se ejecutan. Si pone en cola una nueva función, se coloca en la posición respectiva dentro de esa cola. Después la función actual ha finalizado, el motor toma la siguiente función de la cola (con respecto a los tiempos introducidos, por ejemplo, por setTimeout() y lo ejecuta.
Como resultado, en cada momento se ejecuta una sola función, lo que hace que la ejecución sea prácticamente única. Existen algunas excepciones para los eventos, que se tratan en el siguiente enlace.


Para referencia:


81
2018-02-09 08:10



JavaScript tiene un único subproceso, por lo tanto, mientras está en el bucle, no se ejecuta nada más.


24
2018-02-09 08:11



Para mantener la velocidad real de Chrome sin tener que recuperar constantemente el tiempo para calcular la velocidad, puede probar este código JS:

var start = new Date().getTime()
var i = 0
while(i<1000000)
{
    i++
}
var end = new Date().getTime()
var delta = end-start
var speed = i/delta
console.log(speed + " loops per millisecond")

19
2018-02-09 13:29



Javascript tiene un único subproceso, eso significa que ejecuta solo una instrucción a la vez, secuencialmente.

El sistema de eventos, como en muchos otros idiomas y la biblioteca, es manejado por un ciclo de eventos. El bucle de evento es básicamente un bucle, que en cada iteración comprueba si hay mensajes en la cola y envía eventos.

En javascript (como en mot de idiomas que implementan este patrón), se llama al bucle de evento cuando la pila está vacía, es decir, cuando todas las funciones tienen devoluciones, en otras palabras, al final del código del programa.

Su programa "real" se ve algo así detrás de la escena:

var run = true, i = 0;
setTimeout(function(){ run = false; }, 1);
while(run){ i++; }

while(true) {
/*
 * check for new messages in the queue and dispatch
 * events if there are some
 */
  processEvents();
}

Por lo tanto, el mensaje del reloj que dice que el tiempo de espera ha terminado nunca se procesa.

Más información sobre el ciclo de eventos en: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/EventLoop


Por supuesto que es un poco más complejo, mira aquí esos ejemplos: ¿Se garantiza JavaScript con un solo subproceso? (tl; dr: En algunos motores de navegación, algunos eventos externos no dependen del ciclo de eventos y se activan de inmediato cuando ocurren, adelantando la tarea actual. Pero este no es el caso con setTimeout, que simplemente agrega un mensaje a la cola y nunca se dispara inmediatamente.)


4
2018-02-09 15:16



El ciclo While no tiene acceso al setTimeout. Tiene un código que establece que se ejecuta verdadero, y luego nunca se convertirá en falso.


2
2018-02-09 20:06



JavaScript tiene un solo subproceso y tiene un único subproceso en cualquier lugar.

Creo que esta pregunta está bien: ¿Se garantiza JavaScript con un solo subproceso?

Cuando su código está en loop, otra ocde no se ejecuta y bloquea.


1
2018-02-10 04:31