使用SetTimeout模擬/模仿SetInterVal(JavaScript)


問題背景

  近日我在開發一個答題小程序的時候,需要判斷用戶在規定答題時間內完成所有答題。但是,遇到了一個問題是使用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左右.這個與電腦硬件有關系.所以使用定時器來達到一些精准的任務並不是一個最好的選擇.



參考


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM