問題背景
近日我在開發一個答題小程序的時候,需要判斷用戶在規定答題時間內完成所有答題。但是,遇到了一個問題是使用setInterval(func,time)
的時候。擔心會遇到一些問題。造成這個擔心的原因是因為之前開發VUE單頁應用的時候.從別的選項卡切換當前網頁選項卡的時候.當前網頁的倒計時會一度變得不如預期所想的那樣(1s變一下數字)。而是倒計時的速度變得非常快。
於是,網上查到了如何使用setTimeOut()
來模擬setInterVal()
。
代碼
var timer;
var i = 1;
timer = function () {
i++;
console.log(i);
if (i == 10) {
timer = function () {
console.log("終止運行");
}
}
setTimeout(timer, 500);
};
console.log(timer);
setTimeout(timer, 500);
剛開始理解這段代碼的時候,我有點不知所以然.但是現在覺得是非常容易理解的.在這段函數是timer指向了一個內存空間的對象的引用(這個對象可以執行一些動作,它就是函數).
而setTimeout
會在倒計時結束之后去回調這個函數.而在回調這個函數到函數執行體內的時候,又會去設置一個定時器.這個定時器的回調函數指向了一個內存空間的引用.這還是Timer.所以它會起到模擬setInterval的效果.
同時,這種寫法也是更為可控的.
如何取消這個定時器.只需要把timer設置為別的值,或者指向別的引用就可以了.
timer = function () {
console.log("終止運行");
}
以下是一種函數的寫法
let timer = null;
interval(func, wait){
let interv = function(){
func.call(null);
timer=setTimeout(interv, wait);
};
timer= setTimeout(interv, wait);
},
interval(function() {}, 20);
在Vue2.x中,需要將timer
定義在data屬性中,比如說timer=function(){}.[JS變量類型的轉換會額外消耗性能].清除定時器需要使用this.timer
.
需要注意的是定時器並不是嚴格按照預期時間去執行的.它可能提前或者延遲執行.這和Javascript的語言特性有關.眾所周知JavaScript是單線程語言.JavaScript的多線程和異步是依靠於EventLoop
(事件循環)機制來進行實現的.語言特性決定了定時器總是趨近於設定時間去執行的.
setTimeout(function () {
console.log("等等我呀");
console.timeEnd('caltime');
}, 1000);
console.log('我先執行咯');
console.time('caltime');
// 以下代碼僅用於消耗調用棧的執行時間
var speedTime = [];
for (var i = 0; i < 100000000; i++) {
speedTime.push(i);
}
以上代碼經過實際測試會發現,定時器的調用間隔不是1s.我這里經過測試是2s左右.這個與電腦硬件有關系.所以使用定時器來達到一些精准的任務並不是一個最好的選擇.