2013-03-05 34 views
0

我一直在玩HTML5和Canvas,所以我會很高興爲我正在做的事情提供一個恆定的幀率。爲此,我試圖使用JavaScript的setInterval,但似乎setInterval比期望的循環更快。SetInterval發生得比預期的要快

出於測試目的,我編造了一個小的測試腳本,內容如下:

var start = new Date(); 
var frames = 0; 

setInterval(function() { 
    frames++; 
    var d = new Date(); 
    if (d.getTime() - start.getTime() > 1000) { 
     console.log(frames); 
     frames = 0; 
     start = d; 
    } 
}, 1000/60); 

此腳本理應打印許多「幀」如何在一秒鐘內進行計數。如果setInterval正常工作,它會在控制檯上不斷打印「60」。但是,Chrome和Firefox給我每秒63幀,而Internet Explorer 9給我每秒66到67幀(總是最差的違規者)。

將1000毫秒提高到20000,在Chrome上我平均爲62.5 fps,在Firefox上爲62.4 fps,在Internet Explorer上爲66.0。

我讀過這個very enlightening article on Mozilla關於setTimeout他們提到「夾緊」,我認爲這可能是一個可能的原因。但是,對於60fps,超時將是16.6ms,比所使用的任何夾具都高。

我也認爲這可能是一個計時器錯誤,給我一個或兩個框架關閉,但與20000毫秒測試返回相同的平均幀數,所以它不是定時器。

關於我在做什麼錯的任何想法?這是一個非常奇怪的行爲。對於任何反饋,我們都表示感謝。

回答

1

爲setTimeout的延遲是一個整數(毫秒)。 1000/6016.67,它被截斷爲161000/1662.5。 IE的時鐘以15ms的增量運行,因此它可能以15ms的間隔運行該功能,因此66.7 fps。

所有符合你觀察到的行爲。

最重要的是,你有setTimeout和setInterval的變化無法準確地運行在所請求的延遲,所以如果系統突然變得忙碌(例如響應網絡請求,滾動操作等)幀速率將會變慢或變得生澀,試圖趕上。

0

不幸的是,這種方法不會產生一致的結果。您必須考慮有問題的腳本的實際執行時間,儘可能短。

我聽說requestAnimationFrame在這個用途上效果更好。

A snippet from the Mozilla Developer Network about it.

A nice article about it

+0

如果[John Resig](http://ejohn.org/blog/how-javascript-timers-work/)是正確的(他似乎至少在這一點上),setInterval不會等待(如果它那麼,OP的結果會不同)。它將以指定的時間間隔安排新的呼叫,即使最後一個仍在執行。如果有人在等待被叫,它不會排隊。 – RobG 2013-03-05 08:32:24

+0

非常感謝,這個功能看起來很有趣。我認爲我的應用程序足夠輕量,以確保它不會達到文章中描述的計時器上限。 – 2013-03-05 11:40:49