working not ejemplo cleartimeout javascript settimeout

not - ¿Cuál es la razón por la cual JavaScript setTimeout es tan inexacto?



sleep javascript (3)

Tengo este código aquí:

var date = new Date(); setTimeout(function(e) { var currentDate = new Date(); if(currentDate - date >= 1000) { console.log(currentDate, date); console.log(currentDate-date); } else { console.log("It was less than a second!"); console.log(currentDate-date); } }, 1000);

En mi computadora, siempre se ejecuta correctamente, con 1000 en la salida de la consola. Interesantemente en otra computadora, el mismo código, la devolución de llamada de tiempo de espera comienza en menos de un segundo y la diferencia de currentDate - date está entre 980 y 998.

Sé que existen bibliotecas que resuelven esta inexactitud (por ejemplo, Tock ).

Básicamente, mi pregunta es: ¿Cuáles son las razones porque setTimeout no se setTimeout en el retraso dado? ¿Podría ser la computadora demasiado lenta y el navegador automáticamente intenta adaptarse a la lentitud y dispara el evento antes?

PD: Aquí hay una captura de pantalla del código y los resultados ejecutados en la consola JavaScript de Chrome:


Alguien por favor corrígeme si estoy malinterpretando esta información:

De acuerdo con una ejohn.org/blog/accuracy-of-javascript-time sobre la inexactitud de las pruebas de rendimiento en todas las plataformas (énfasis mío)

Con los tiempos del sistema constantemente redondeados al último tiempo consultado ( cada uno con una separación de 15 ms ), la calidad de los resultados de rendimiento se ve seriamente comprometida.

De modo que hay hasta 15 ms fudge en cada extremo cuando se compara con la hora del sistema.


En general, los programas de computadora son muy poco confiables cuando se intenta ejecutar cosas con una precisión mayor que 50 ms. La razón de esto es que incluso en un procesador octahreh Hyperhreaded el sistema operativo suele hacer malabares con varios cientos de procesos y subprocesos, a veces miles o más. El sistema operativo hace que todas las multitareas funcionen programando todas ellas para obtener un trozo de tiempo de CPU, una tras otra, lo que significa que obtienen ''unos pocos milisegundos de tiempo para hacer lo suyo''.

Implicidad esto significa que si establece un tiempo de espera de 1000 ms, es probable que el proceso actual del navegador ni siquiera se ejecute en ese momento, por lo que es perfectamente normal que el navegador no lo note hasta 1005, 1010 o incluso 1050 milisegundos que debería estar ejecutando la devolución de llamada dada.

Por lo general, esto no es un problema, sucede, y rara vez es de suma importancia. Si es así, todos los sistemas operativos suministran temporizadores de nivel de kernel que son mucho más precisos que 1 ms, y permiten que un desarrollador ejecute código exactamente en el punto correcto en el tiempo. JavaScript, sin embargo, como un entorno muy aislado, no tiene acceso a objetos kernel como ese, y los navegadores se abstienen de usarlos ya que teóricamente podría permitir que alguien ataque la estabilidad del sistema operativo desde una página web, construyendo cuidadosamente código que muera de hambre hilos al inundarlo con una gran cantidad de temporizadores peligrosos.

En cuanto a por qué la prueba arroja 980, no estoy seguro, eso dependería exactamente de qué navegador esté usando y qué motor de JavaScript. Sin embargo, puedo comprender completamente si el navegador corrige manualmente un poco hacia abajo para la carga y / o velocidad del sistema, asegurando que "en promedio, la demora es aún la hora correcta" - tendría mucho sentido, desde el principio de sandboxing hasta Aproxime la cantidad de tiempo requerida sin potencialmente cargar el resto del sistema.


No se supone que sea particularmente preciso. Hay una serie de factores que limitan la rapidez con que el navegador puede ejecutar el código; Citando de MDN :

Además del "pinzamiento", el tiempo de espera también puede dispararse más tarde cuando la página (o el OS / navegador mismo) está ocupado con otras tareas.

En otras palabras, la forma en que usualmente se implementa setTimeout , solo se ejecuta después de un retraso determinado, y una vez que el hilo del navegador es libre de ejecutarlo.

Sin embargo, diferentes navegadores pueden implementarlo de diferentes maneras. Aquí hay algunas pruebas que hice:

var date = new Date(); setTimeout(function(e) { var currentDate = new Date(); console.log(currentDate-date); }, 1000); // Browser Test1 Test2 Test3 Test4 // Chrome 998 1014 998 998 // Firefox 1000 1001 1047 1000 // IE 11 1006 1013 1007 1005

Tal vez las <1000 veces de Chrome podrían atribuirse a la inexactitud en el tipo de Date , o tal vez podría ser que Chrome utilice una estrategia diferente para decidir cuándo ejecutar el código; tal vez intente encajarlo en el intervalo de tiempo más cercano, incluso si el tiempo de espera no se ha completado aún.

En resumen, no debe usar setTimeout si espera una temporización confiable, consistente y de escala de milisegundos.