2012-06-04 11 views
6

Me he encontrado con un problema extraño en Firefox 12. setTimeout() no parece esperar siempre la longitud adecuada. ¿O quizás son los milisegundos de la fecha los que no funcionan?Firefox invoca la función setTimeout demasiado pronto (o Date.getTime() está desactivado?)

Check out this fiddle. Esencialmente, un setTimeout de 100ms parece funcionar entre 80ms y 110ms. Más puedo entender, basado en John Resig's explanation of timers. ¿Pero menos?

Es posible que deba actualizarlo una o dos veces para ver el problema, ya que a veces funciona correctamente en la primera ejecución. Parece funcionar spifftacular en IE y Chrome.

Aquí está el código que estoy utilizando en mi violín:

var txt = '', 
    TIMEOUT_LENGTH = 100, 
    _now; 

now = Date.now || function() { return new Date().getTime() }; 

function log(time) { 
    c = time < 100? 'class="error"' : ''; 
    $('#log').append('<p '+c+'>waited ' + time + '</p>'); 
} 

function defer() { 
    var d = $.Deferred(), 
     start = now(); 
    setTimeout(function() { 
     d.resolve(now() - start); 
    }, TIMEOUT_LENGTH); 
    return d.promise(); 
} 

for (var i = 0; i < 20; i++) { 
    defer().then(log); 
} 

He aquí una muestra de la salida peculiar:

enter image description here

Aquí está mi información navegador:

enter image description here

Y gracias tan muc h por leer mi pregunta! Espero que alguien pueda arrojar algo de luz sobre esto.

MÁS INFORMACIÓN

trabajé alrededor del problema utilizando setInterval() y comprobando cada incremento para ver si ha transcurrido el tiempo necesario. See this fiddle.

Sin embargo, todavía estoy muy interesado en saber si alguien puede arrojar algo de luz en el origen del problema

+1

Puedo confirmar este comportamiento en Firefox 12 en OS X 10.7. Safari proporciona entre 100 y 105 para mí, Firefox 12 80s-110s para la primera ejecución, las siguientes corridas fueron ... 95-105. – Aaron

+0

Me alegra saber que no soy solo yo :) – Kato

+0

Así que eso es todo lo que tenemos entonces. Tal vez abra un error en Mozilla solo para ver lo que dicen :) – Kato

Respuesta

3

Sí. La precisión de setTimeout se basa en muchos factores, y no se garantiza que se ejecute siempre en el momento exacto que especifique.

No puedo decir esto con autoridad, pero supongo que Firefox, en un intento de parecer más rápido, acelerará el motor JS temporalmente para poner todo en movimiento (lo cual es interesante, porque en mi experiencia En realidad, las funciones basadas en temporizador se ejecutan más lentamente inicialmente en mi versión de Firefox.

Ni setTimeout ni setInterval prometen que se ejecutarán en el momento preciso, como indica el enlace que publicó. Sin embargo, con setInterval, obtienes el beneficio de que el ciclo del temporizador hace lo posible para "corregirse a sí mismo" poniéndose al día si queda muy rezagado, por lo que para lo que estás tratando de hacer, puede ser más apropiado.

De todos modos, aquí están mis resultados en mi Macbook 10.6.8:

Firefox 5.0.1:

waited 92 
waited 92 
waited 93 
waited 93 
waited 93 
waited 93 
waited 93 
waited 94 
waited 93 
waited 93 
waited 93 
waited 93 
waited 94 
waited 94 
waited 94 
waited 94 
waited 94 
waited 95 
waited 96 
waited 96 

Safari 5.1.5:

waited 100 
waited 104 
waited 104 
waited 103 
waited 104 
waited 104 
waited 104 
waited 104 
waited 104 
waited 104 
waited 104 
waited 104 
waited 104 
waited 104 
waited 104 
waited 104 
waited 104 
waited 104 
waited 104 
waited 104 

Chrome 19.0.1084.52:

waited 101 
waited 103 
waited 103 
waited 104 
waited 104 
waited 103 
waited 103 
waited 103 
waited 103 
waited 103 
waited 103 
waited 103 
waited 103 
waited 103 
waited 104 
waited 104 
waited 104 
waited 104 
waited 104 
waited 104 
+0

FWIW, 'setInterval' es la forma en que he resuelto el problema. Solo compruebo el intervalo de tiempo en cada tic y cierro una vez que se han alcanzado los 100ms, para asegurarme de que no caiga por debajo del mínimo. Sin embargo, este sigue siendo un problema muy intrigante del que me gustaría escuchar una explicación (ya que parece que nunca debería ejecutarse antes de la duración establecida). – Kato

+0

Además, la falta de gente quejándose sobre este tema fue un poco sorprendente, así que todavía tengo curiosidad si me falta algo obvio :) – Kato

+0

Solo un lado, Firefox 5 es bastante 'viejo' en este punto considerando que tienes Safari y Chrome actualizado. – Aaron

1

JavaScript is synchron ous.El navegador agregará su setTimeout s a la cola y ejecutarlas después

  1. La cuenta atrás ha terminado
  2. Ha terminado todas las demás tareas que están en la cola en el momento de la cuenta atrás ha terminado.
+1

¡Hola, gracias! Desafortunadamente, eso realmente no explica por qué invocaría la función antes del tiempo especificado en 'setTimeout' o por qué Firefox se comporta de manera diferente que otros navegadores. – Kato

1

Escribí la siguiente función para asegurarme de que mi código se ejecuta después de al menos la cantidad dada de milisegundos. Lo uso en lugar de setTimeout

mySetTimeout=function(f,t){ 
    var endTime=new Date().valueOf()+t; 
    setTimeout(function(){ 
     var now=new Date().valueOf(); 
     if(now<endTime){ 
      mySetTimeout(f,endTime-now); 
     }else{ 
      f(); 
     } 
    },t); 
}; 
Cuestiones relacionadas