js異步之setTimeout與setInterval

基本介紹

  • setTimeout 延時執行

    setTimeout(fn,1000),1000ms後執行fn
  • setInterval 定時器

    setInterval(fn,100),每隔100m執行fn

特別注意

  • setTimeout執行時間可能會大於給定時間。
  • setInterval間隔執行的時間可能會小於給定時間。

setTimeout

  • JavaScript引擎在執行setTimeout(fn, 10)時,一方面繼續執行setTimeout(fn, 10)後面的同步代碼,同時另外一方面開始計時,在10ms以後將fn插入任務隊列中。待全部同步代碼執行結束後(JavaScript引擎空閒),依次任務隊列中的異步代碼。因此,setTimeout(fn, 10)並不能準確的在10ms以後執行,而是大於等於10ms。
  • 代碼一(正常)
console.time("time")
setTimeout(function(){console.timeEnd("time")},10);
複製代碼

輸出:time:10.9619140625ms異步

  • 代碼二(超時)
console.time();
var i = 0;
for(var s =1;s<100000;s++){
	i += s;
};
setTimeout(function(){console.timeEnd()},10);
複製代碼

輸出:time:24.440185546875ms動畫

setInterval

  • 與setTimeout()相同的是,若是當前沒有同步代碼在執行(JavaScript引擎空閒),則定時器對應的方法fn會被當即執行,不然,fn就會被加入到任務隊列中。
  • 因爲定時器的事件是每隔10ms就觸發一次,有可能某一次事件觸發的時候,上一次事件的處理方法fn尚未機會獲得執行,仍然在等待隊列中,這個時候,這個fn事件就被丟棄,繼續開始下一次計時。
  • 須要注意的是,因爲JavaScript引擎這種單線程異步的執行方式,有可能兩次fn的實際執行時間間隔小於設定的時間間隔。好比上一個定時器事件的處理方法觸發以後,等待了5ms纔得到被執行的機會。而第二個定時器事件的處理方法被觸發以後,立刻就被執行了。那麼這二者之間的時間間隔實際上只有5ms。
var IntervalId= setInterval(function(){console.log(Date.now())},10);
var i = 0;
for(var s =1;s<1000000;s++){
	i += s;
};
setTimeout(function(){clearInterval(IntervalId)},100);
複製代碼

輸出:ui

1525943129602
1525943129607 // 距離上一次只間隔了5ms
1525943129618
1525943129628
1525943129639
1525943129648
1525943129657
1525943129669
1525943129678
1525943129688
1525943129699
複製代碼
  • setInterval()並不適合實現精確的按固定間隔的調度操做。
  • 好比在處理動畫幀數時,就不適合用setInterval,而應採用requestAnimationFrame方法。
// 簡單粗暴的方法
var FPS = 60;
setInterval(draw, 1000/FPS);
// 當draw方法執行耗時大於1000/60 ms時,就會發生丟幀的現象。
複製代碼

總結

setTimeout()和setInterval()都不能知足精確的時間間隔。假如設定的時間間隔爲10ms,則setTimeout(fn, 10)中的fn執行的時間間隔可能大於10ms,而setInterval(fn, 10)中fn執行的時間間隔可能小於10ms。spa

相關文章
相關標籤/搜索