在js中若是打算使用setInterval進行倒數,計時等功能,每每是不許確的,由於setInterval的回調函數並非到時後當即執行,而是等系統計算資源空閒下來後纔會執行.而下一次觸發時間則是在setInterval回調函數執行完畢以後纔開始計時,因此若是setInterval內執行的計算過於耗時,或者有其餘耗時任務在執行,setInterval的計時會愈來愈不許,延遲很厲害.javascript
下面的代碼能夠說明這個問題java
var startTime = new Date().getTime(); var count = 0; //耗時任務 setInterval(function(){ var i = 0; while(i++ < 100000000); }, 0); setInterval(function(){ count++; console.log(new Date().getTime() - (startTime + count * 1000)); }, 1000);
代碼裏輸出了setInterval觸發時間和應該正確觸發時間的延遲毫秒數函數
176 340 495 652 807 961 1114 1268 1425 1579 1734 1888 2048 2201 2357 2521 2679 2834 2996 ......
能夠看到延遲是愈來愈嚴重的.blog
爲了在js裏可使用相對準確的計時功能,咱們能夠ip
var startTime = new Date().getTime(); var count = 0; setInterval(function(){ var i = 0; while(i++ < 100000000); }, 0); function fixed() { count++; var offset = new Date().getTime() - (startTime + count * 1000); var nextTime = 1000 - offset; if (nextTime < 0) nextTime = 0; setTimeout(fixed, nextTime); console.log(new Date().getTime() - (startTime + count * 1000)); } setTimeout(fixed, 1000);
代碼裏,經過1000(也就是週期時間)減去當前時間和準確時間的差距,來算出下次觸發的時間,從而修正了當前觸發的延遲.資源
下面是輸出get
186 200 230 271 158 899 900 899 900 899 899 899 902 899 418 202 232 266 145 174 192 214 242 268 149 179 214 ......
能夠看到雖然觸發時間並不是絕對準確,但因爲每次觸發都進行及時修正,因此並無形成偏差積累.回調函數