2012-01-27 5 views
7

Prefazione: ho un demo of the problem sul mio sito personale (spero che sia ok, altrimenti posso provare a configurarlo su jsfiddle). Sto pensando che questa domanda sia un po 'divertente, mentre cerco anche di capire le funzioni del tempo in javascript.Come posso far funzionare le mie funzioni setTimout alla stessa velocità?

Sto incrementando il valore delle barre di avanzamento su un timeout. Idealmente (se le funzioni funzionano istantaneamente) dovrebbero riempire alla stessa velocità, ma nel mondo reale non lo fanno. Il codice è questo:

function setProgress(bar, myPer) { 
bar.progressbar({ value: myPer }) 
    .children('.ui-progressbar-value') 
     .html(myPer.toPrecision(3) + '%') 
      .attr('align', 'center'); 
    myPer++; 
    if(myPer == 100) { myPer = 0; } 
} 

function moveProgress(bar, myPer, inc, delay){ 
    setProgress(bar, myPer); 
    if(myPer >= 100) { myPer = 0; } 
    setTimeout(function() { moveProgress(bar, myPer+inc, inc, delay); }, delay); 
} 

$(function() { 
    moveProgress($(".progressBar#bar1"), 0, 1, 500); 
    moveProgress($(".progressBar#bar2"), 0, 1, 500); 
    moveProgress($(".progressBar#bar3"), 0, .1, 50); 
    moveProgress($(".progressBar#bar4"), 0, .01, 5);    
}); 

Ingenuamente, si potrebbe pensare dovrebbe tutti corrono (riempire la barra di avanzamento) alla stessa velocità.

Tuttavia, nelle prime due barre, (se si chiama "impostazione della barra di avanzamento" una singola operazione), eseguo un'operazione ogni 500 ms per un totale di 500 operazioni per riempire la barra; nel terzo, eseguo un'operazione ogni 50ms per un totale di 5.000 operazioni per riempire la barra; nel quarto, eseguo un'operazione ogni 5ms per un totale di 50.000 operazioni per riempire la barra.

Quale parte del mio codice impiega più tempo, causa queste differenze di velocità e potrebbe essere modificata per far sì che sembrino funzionare nel modo in cui lo fanno (la quarta barra ottiene incrementi più piccoli), ma anche a la stessa velocità?

+0

Se si guarda bene, le etichette sono spente sul sito di esempio. Non è il 4 ° bar .01 ogni 5ms? –

+0

@JamesMontagne whoops. Grazie. Fisso. – xdumaine

+0

nota che il ritardo di una chiamata 'setTimeout' può essere bloccato su un valore minimo; 4ms per i browser html5 (e Chrome) ma dipende dal browser. cioè può bloccarlo ad un valore maggiore come 10ms. –

risposta

3

Il problema più grande con l'utilizzo di setTimeout per cose come questa è che l'esecuzione del codice avviene tra i timeout e non viene conteggiata nel valore inviato a setTimeout. Se il tuo ritardo è di 5 ms e il tuo codice impiega 5 ms per eseguire, stai essenzialmente raddoppiando il tuo tempo.

Un altro fattore è che una volta scaduto il timeout, se un altro pezzo di codice è già in esecuzione, dovrà attendere il termine, ritardando l'esecuzione.

Questo è molto simile ai problemi che si verificano quando si tenta di utilizzare setTimeout per un orologio o un cronometro. La soluzione è confrontare l'ora corrente con il tempo di avvio del programma e calcolare il tempo in base a quello. Potresti fare qualcosa di simile. Controlla quanto tempo è passato da quando hai iniziato e imposta% in base a quello.

+0

Ahh, quindi la barra sembrerebbe incrementare a un ritmo regolare, dal momento che è iniziato ad aumentare, ma è un nuovo calcolo ogni volta, in modo da recuperare il tempo perduto in ritardi e operazioni in coda? – xdumaine

+0

Fondamentalmente. Potresti essere leggermente fuori sincrono per un periodo di tempo molto breve, ma tornerebbe sempre indietro la volta successiva che si verifica un timeout. –

+0

Mi rendo conto che si tratta di una sorta di sperimentazione, ma se si trattasse di una situazione reale, probabilmente si vorrebbe un solo timer e si aggiornerebbero tutti e 4 nella stessa esecuzione. Allora saresti sempre sincronizzato. –

0

Quali sono le cause della differenza di velocità due cose: in primo luogo è il fatto che si esegue più codice per riempire la barra inferiore (come si allude al 2 ° all'ultimo paragrafo). Inoltre, ogni volta che si imposta un timeout, il browser lo accoda ... il ritardo effettivo potrebbe essere più lungo di quanto specificato, a seconda di quanto è in coda (vedere MDN on window.setTimeout).

0

Amore la questione, non ho una risposta molto precisa, ma qui sono i miei 2 centesimi:

JavaScript è un linguaggio molto veloce che si occupa molto bene con il suo ciclo di eventi e quindi mangia setTimeouts e setIntervals per la prima colazione .
Ci sono dei limiti però, e dipendono da un gran numero di fattori, come browser e la velocità del computer, la quantità di funzioni che si hanno sul ciclo di eventi, la complessità del codice da eseguire e valori di timeout ...

In questo caso, penso sia ovvio che se si tenta di eseguire una funzione ogni 500 ms, si comporterà molto meglio dell'esecuzione ogni 50 ms, quindi molto meglio di ogni 5 ms. Se si tiene conto del fatto che si stanno eseguendo tutti l'uno sopra l'altro, è possibile prevedere che le prestazioni non saranno ottimali.

Puoi provare questo esercizio:
prendere il 500ms e lanciarlo da solo.segna il tempo totale impiegato per riempire la barra (proprio qui vedrai che ci vorrà un po 'più del previsto).
prova a eseguire due timeout di 500 ms contemporaneamente e osserva che il tempo totale è stato leggermente più lungo.
Se si aggiungono 50ms e quindi 5ms, si noterà che si perderanno prestazioni ogni volta ...

Problemi correlati