相信大家在寫Javascript時常常會用到Timer,一定會馬上想到用setInterval這個異步方法。然而,你有沒想過用setTimeout加上遞迴的方式去實作一個setInterval,孰優孰劣?
最近剛好有個需求要使用setInterval來觸發事件,所以查了一下發現有人用setTimeout來實現setInterval,當時就在想為什麼要大費周章去實作呢?事出必有因,經過Google後,讓我認識了裡面的意義,若你還不知,希望這篇短文讓你長點知識。
異步Timer的注意事項
若要實作一個異步Timer,通常會考量這兩個層面:
- 準確性(時間)
- 完整性(資料)
這邊說明一下,時間的準確性就是每次的循環都非常的準確,沒有任何的誤差。例如:每次以一秒來循環,程式要求每秒鐘一定要準時觸發事件。完整性就是指,所觸發的事件若反應時間過慢,超過了等待時間,依然要能保證資料回覆的完整性。也就是說這兩這基本上是互斥的。你要保證準確性,就無法保證完整性。反之亦然。說一下小結:所以在javascript的世界中,你若想要確保準確性,請使用setInterval。若想確保完整性,請用setTimeout實作。做一個小表格如下:
Timer特性 | setInterval | setTimeout |
---|---|---|
準確性 | V | |
完整性 | V |
使用場景
好了,說了那麼多,直接介紹一些使用場景吧。簡單的說就是如果你的間隔時間越短越建議使用setTimeout來實作Timer,因為你逾時的機率很大。或者,所觸發的事件不可預期且時間較長(I/O bound),像是一個ajax請求等等。這時候非常建議使用setTimeout。還有一種場景,一定要保證資料不會漏失,例如背景作業來追蹤使用者行為等等。其他的時候其實使用setInterval就可以了。
用setTimeout實作Timer
最後附上一小段用setTimeout實作Timer的code:
Timer(method, time) {
let timeout;
function loop() {
timeout = setTimeout(function() {
method();
loop();
}, time);
}
loop();
return {
cancel: function cancel() {
clearTimeout(timeout);
}
};
}
PK結果沒有孰優孰劣,完全看你要使用的場景是什麼喔~謝謝大家。