亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

淺談對于“不用setInterval,用setTimeout”的理解

發布時間:2020-09-01 13:31:06 來源:腳本之家 閱讀:175 作者:小利子 欄目:web開發

JavaScript高級程序設計(第三版)(以下簡稱紅寶書)22.3高級定時器中詳細介紹了定時器setTimeout和setInterval,看完書后,深入理解了二者的區別,結合前輩們給我的建議“用setTimeout,不要用setInterval”,寫下此文,分析這個建議的合理性。
這兩個家伙看上去長得差不多,func是要執行的函數,interval是時間間隔。

setTimeout(func,interval)
setInterval(func,interval)

關于時間間隔,紅寶書中這么說:

設定一個 150ms 后執行的定時器不代表到了 150ms 代碼就立刻執行,它表示代碼會在 150ms 后被加入到隊列中。如果在這個時間點上,隊列中沒有其他東西,那么這段代碼就會被執行。

對于這個時間間隔的理解非常重要!步入正題,為何不用setInterval,因為它可能會帶來兩個問題:

  • “丟幀”現象
  • 不同定時器的代碼的執行間隔比預期小

一圖勝千言,如下圖所示,讓我們跟著時間線看看這樣的問題怎么發生的。假定一個場景,在click事件中設置了setInterval(func,500),假設click事件和定時器內函數的執行時間都是1s,為了方便陳述,我把不同時間觸發的func取了不同的名字,實際上接下來的func1=func2=func3=func。在0s處觸發click事件,click事件執行,在0.2s處觸發定時器,0.7s處第一個函數func1加入到事件隊列,但由于JS引擎是單線程的,click事件還在執行,所以func1等待著,等到1s處,click事件執行完畢,fun1才開始執行。按照定時器的時間間隔,1.2s處第二個函數func2加入到事件隊列,但此時fun1正在執行,所以func2只能等待。0.5s后,也就是1.7s處,第三個函數func理應加入事件隊列,但是JS引擎做了一個事情:

當使用 set Interval()時,僅當沒有該定時器的任何其他代碼實例時,才將定時器代碼添加到隊列中。

在1.7s處,func1在執行,func2在隊列里等待執行,func2就是該定時器的代碼實例,按照JS引擎的處理,func3不會加入到事件隊列里,更別說執行了,這就導致出現了“丟幀”現象。而在圖中也可以注意到,func1執行完畢,線程空閑了,func2就可以執行了,這就使得func1和func2之間的執行沒有時間間隔,這跟我們所預期的500ms產生一次結果是不同的。

淺談對于“不用setInterval,用setTimeout”的理解

而如果使用鏈式setTimeout調用,每次函數執行的時候都會創建一個新的定時器。第二個setTimeout()調用使用了 arguments.callee 來獲取對當前執行的函數的引用,并為其設置另外一個定時器。這樣做的好處是,在前一個定時器代碼執行完之前,不會向隊列插入新的定時器代碼,確保不會有任何缺失的間隔。而且,它可以保證在下一次定時器代碼執行之前,至少要等待指定的間隔,避免了連續的運行。代碼如下所示

setTimeout(function(){
  //do something
  setTimeout(arguments.callee,interval);
},interval)

用setTimeout方法的話,上面假設的場景就發生了改變,如下圖所示,在0s處觸發click事件,click事件執行,在0.2s處觸發定時器,0.7s處第一個函數func1加入到事件隊列,click事件執行了1s,在1s處func1執行,2s處func1執行結束,第二個setTimeout定時器才被觸發,0.5s后將函數func2加入隊列,此時隊列為空,func2開始執行,3.5s處func2執行結束,又一個setTimeout定時器被觸發,0.5s后將函數func3加入隊列,此時隊列為空,func3開始執行。。。

淺談對于“不用setInterval,用setTimeout”的理解

通過上面這個場景,我們能知道當需要用定時器來設置一個操作重復執行,并且這個操作需要執行一定的時間,記得用setTimeout,不用setInterval!

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

准格尔旗| 伊宁市| 大荔县| 韶关市| 邻水| 商水县| 鹤岗市| 密云县| 安达市| 博乐市| 龙南县| 西城区| 隆回县| 鹤岗市| 蒙城县| 新安县| 双桥区| 班戈县| 昌黎县| 开封市| 江永县| 会昌县| 全椒县| 建昌县| 锡林浩特市| 望奎县| 河北省| 贵阳市| 都昌县| 庆云县| 饶阳县| 改则县| 莒南县| 抚顺县| 思南县| 信阳市| 海晏县| 于都县| 盈江县| 鄂伦春自治旗| 梅河口市|