2012-06-04 13 views
6

Ho incontrato uno strano problema in Firefox 12. setTimeout() non sembra attendere sempre la lunghezza appropriata. O forse sono i millisecondi della data che non fanno jive?Firefox richiama la funzione setTimeout troppo presto (o Date.getTime() è disattivato?)

Check out this fiddle. In sostanza, un setTimeout di 100 ms sembra funzionare ovunque tra 80 ms e 110 ms. Più posso capire, basato su John Resig's explanation of timers. Ma meno?

Potrebbe essere necessario aggiornarlo una o due volte per vedere il problema, poiché a volte funziona correttamente alla prima esecuzione. Sembra funzionare spifftacular in IE e Chrome.

Ecco il codice che sto utilizzando nel mio violino:

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); 
} 

Ecco un esempio di output eccentrico:

enter image description here

Ecco le mie informazioni del browser:

enter image description here

E grazie così muc h per aver letto la mia domanda! Spero che qualcuno possa far luce su questo.

INFO

ho lavorato tutto il problema utilizzando setInterval() e controllando ogni incremento per vedere se il tempo richiesto è passato. See this fiddle.

Tuttavia, sono ancora molto interessati a sentire se qualcuno può far luce nella fonte del problema

+1

Posso confermare questo comportamento in Firefox 12 su OS X 10.7. Safari fornisce ovunque tra 100 e 105 per me, Firefox 12 80s-110s per la prima esecuzione, le esecuzioni successive erano ... 95-105. – Aaron

+0

Felice di sentire che non sono solo io :) – Kato

+0

Quindi questo è tutto ciò che otteniamo allora. Forse aprirò un bug su mozilla solo per vedere cosa dicono :) – Kato

risposta

3

Sì. La precisione di setTimeout si basa su molti fattori e non è garantita l'esecuzione sempre nell'esatto momento specificato.

Non posso dirlo con alcuna autorità, ma azzarderò un'ipotesi che Firefox, nel tentativo di sembrare più veloce, acceleri temporaneamente il motore JS per ottenere tutto in movimento (il che è interessante, perché nella mia esperienza le funzioni basate su timer in realtà vengono eseguite inizialmente più lentamente inizialmente nella mia versione di firefox).

setTimeoutsetInterval promettono che verranno eseguiti nel momento esatto, come indicato dal link che hai postato. Tuttavia, con setInterval, si ottiene il beneficio del ciclo del timer facendo tutto il possibile per "correggersi" recuperando se è troppo indietro, quindi per qualsiasi cosa si stia tentando di fare, potrebbe essere più appropriato.

Comunque, ecco i miei risultati sul mio 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' è il modo in cui ho risolto il problema. Controllo l'intervallo di tempo su ogni tick e chiudo una volta raggiunto 100ms, per assicurarmi che non scenda al di sotto del minimo. Tuttavia, questo è ancora un problema molto intrigante che mi piacerebbe sentire una spiegazione (poiché sembra che non dovrebbe mai funzionare prima della lunghezza impostata). – Kato

+0

Inoltre, la mancanza di persone che si lamentano di questo problema è stata un po 'sorprendente, quindi sono ancora curioso di sapere se mi manca qualcosa di ovvio :) – Kato

+0

Solo a parte, Firefox 5 è piuttosto "vecchio" a questo punto considerando che hai Safari e Chrome aggiornati. – Aaron

1

JavaScript è sincronico unità organizzative.Il browser aggiungere i setTimeout s alla coda ed eseguirli dopo

  1. Il conto alla rovescia è finito
  2. ha finito tutti gli altri compiti che sono in coda al momento il conto alla rovescia è finito.
+1

Hey, grazie! Sfortunatamente, questo non spiega in realtà perché dovrebbe richiamare la funzione prima del tempo specificato in 'setTimeout' o perché Firefox si comporta diversamente dagli altri browser. – Kato

1

Ho scritto la seguente funzione per assicurarmi che il mio codice venga eseguito dopo almeno il dato numero di millisecondi. Lo uso invece di 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); 
}; 
Problemi correlati