欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

 更新時間:2019年08月28日 09:33:37   作者:小利子  
這篇文章主要介紹了淺談對于“不用setInterval,用setTimeout”的理解,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

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

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

關(guān)于時間間隔,紅寶書中這么說:

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

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

  • “丟幀”現(xiàn)象
  • 不同定時器的代碼的執(zhí)行間隔比預(yù)期小

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

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

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

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

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

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

通過上面這個場景,我們能知道當(dāng)需要用定時器來設(shè)置一個操作重復(fù)執(zhí)行,并且這個操作需要執(zhí)行一定的時間,記得用setTimeout,不用setInterval!

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

最新評論