setlnterval 的作用是每隔一段指定時間執行一個函式,但是這個執行不是真的到了時間立即執行,它真正的作用是每隔一段時間將事件加入事件佇列中去,只有噹噹前的執行棧為空的時候,才能去從事件佇列中取出事件執行。所以可能會出現這樣的情況,就是當前執行棧執行的時間很長,導致事件佇列裏邊積累多個定時器加入的事件,當執行棧結束的時候,這些事件會依次執行,因此就不能到間隔一段時間執行的效果。
針對 setlnterval 的這個缺點,我們可以使用 setTimeout 遞迴呼叫來模擬 setlnterval,這樣我們就確保了只有一個事件結束了,我們纔會觸發下一個定時器事件,這樣解決了 setlnterval 的問題。
實現思路是使用遞迴函式,不斷地去執行 setTimeout 從而達到 setInterval 的效果
function mySetInterval(fn, timeout) { // 控制器,控制定時器是否繼續執行 let timer = { flag: true } // 設定遞迴函式,模擬定時器執行 function interval() { if (timer.flag) { fn(); setTimeout(interval, timeout) } } // 啟動定時器 setTimeout(interval, timeout); // 返回控制器 return timer; }