working not loop ejemplos ejemplo javascript infinite-loop single-threaded

javascript - not - timer jquery ejemplos



¿Por qué no setTimeout cancela mi ciclo? (6)

Me preguntaba cuántas veces una declaración JavaScript while (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?


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.


Esto vuelve a la naturaleza de un único subproceso de JavaScript 1 . 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 . Está programado para ejecutarse después de que se ejecute la función actual (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 bucle infinito ( nunca ), la devolución de llamada setTimeout() se ejecutará y se run=false .

Como puede ver, un enfoque setTimeout() no funcionará aquí. Puede solucionarlo comprobando el tiempo en el estado de while , 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 de que 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 la 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:

  • https://.com/a/16757582/1169798

    Aquí se explicó un escenario similar con más detalle

  • https://.com/a/2734311/1169798

    Una descripción más detallada sobre cuándo JS se puede ver como un único subproceso y cuándo no.


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



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, es un poco más complejo, consulte aquí los ejemplos: ¿Se garantiza que JavaScript sea de un solo subproceso? ( tl; dr: en algunos motores de navegador, algunos eventos externos no dependen del bucle de eventos y se activan inmediatamente cuando ocurren, adelantándose a la tarea actual. Pero este no es el caso con setTimeout, que solo agrega un mensaje a la cola y nunca dispara inmediatamente.)


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