首頁  >  文章  >  web前端  >  詳細介紹JavaScript定時器的工作原理

詳細介紹JavaScript定時器的工作原理

php是最好的语言
php是最好的语言原創
2018-08-09 10:22:501368瀏覽

JavaScript計時器的工作原理

標籤(空格分隔): JavaScript計時器


最近在看ajax原理的時候,看到了一篇國外的文章,講解了JavaScript定時器的工作原理,幫助我很好的理解了js的單線程工作模式。在這裡翻譯一下供大家參考,原文地址.
翻譯正文
從根本上講,了解JavaScript定時器的工作原理非常重要。通常 js的單線程表現的。讓我們先來看看可以建構和操作定時器的三個函數。

 - 启动单个定时器,在延迟后调用指定的功能。该函数返回一个唯一的ID,该Id可以用于取消定时器    var id = setTimeout(fn, delay); 
 - 类似setTimeout但不断地调用函数(每次都有延迟),直到它被取消,类似于定时任务。同上也返回唯一ID用于取消定时器    var id = setInterval(fn, delay); 
 - 接受计时器ID(由上述任一功能返回)并停止触发计时器回调。
    clearInterval(id);
    clearTimeout(id);

為了理解定時器的內部運作原理,我們需要探索一個重要的概念:定時器延遲並不能保證準確。由於瀏覽器中的所有JavaScript都在單一執行緒上執行,因此非同步事件(例如滑鼠點擊和計時器)僅在可執行時執行。使用圖表可以最好地證明這一點,如下所示:

詳細介紹JavaScript定時器的工作原理

這個圖中有很多資訊要理解,完全理解它會讓你更了解非同步JavaScript執行的工作方式。這張圖是一維的:垂直方向,我們有(掛鐘)時間(譯註:左側的時間刻度),以毫秒為單位。藍色框表示正在執行的JavaScript部分。例如,第一個JavaScript區塊執行約18ms,滑鼠點選區塊大約需要11ms,依此類推。

由於JavaScript一次只能執行一段程式碼(由其單執行緒性質決定),因此每個程式碼區塊都「阻塞」其他非同步事件的進度。這意味著當非同步事件發生時(如滑鼠單擊,計時器觸發或XMLHttpRequest完成),它會先排隊等待(翻譯:可以理解為一個隊列)以後執行(這種排隊實際發生的方式因瀏覽器到瀏覽器而異,這裡是做了一個簡單說明)。

首先,在JavaScript的第一個區塊中,啟動兩個計時器:10ms setTimeout和10ms  setInterval。由於計時器啟動的位置和時間,它實際上在我們實際完成第一個程式碼區塊之前觸發。但請注意,它不會立即執行(由於線程,它無法執行此操作)而是進入排隊佇列,以便在下一個可用時刻執行。

此外,在第一個JavaScript區塊中,我們看到滑鼠點擊。滑鼠點擊事件關聯的JavaScript回呼(我們永遠不知道使用者何時執行一個操作,因此它被認為是異步的)無法立即執行,因此,與初始計時器一樣,它排隊等待稍後執行。

在JavaScript的初始區塊完成後,執行瀏覽器會立即詢問:佇列中有什麼等待執行的任務?在這種情況下,滑鼠點擊處理程序和計時器回呼都在等待。然後瀏覽器選擇一個(滑鼠點擊回調)並立即執行它。計時器將等到下一個時間被從佇列中取出執行。

請注意,當滑鼠點選處理程序執行時,執行第一個間隔回呼。與計時器一樣,它的處理程序進入排隊等待以後執行。但是,請注意,當再次觸發間隔時(在執行timer程序時),此時Interval的間隔回調被丟棄(譯者註:這裡不是很理解,歡迎留言交流指教。是否是因為已經有interval在排隊? )。如果要在執行大塊程式碼時呼叫間隔回調,間隔回呼將連續加入任務佇列中,它們之間沒有延遲。瀏覽器往往只是簡單的去佇列中取任務直到佇列中沒有其他任務。

事實上,我們可以看到,當間隔本身正在執行時,第三個間隔回呼會觸發。這向我們展示了一個重要的事實:Intervals不關心目前正在執行的內容,它們會不加選擇地排隊。

最後,第二個間隔回呼完成執行後,我們可以看到JavaScript引擎沒有任何任務可以執行。這意味著瀏覽器現在等待發生新的非同步事件。當間隔再次觸發時,在50ms的位置。但是,這一次,沒有任何程式正在執行,所以它會立即被觸發。

讓我們來看一個例子,以便更好地說明setTimeout和setInterval之間的差異。

setTimeout(function(){
  /* Some long block of code... */
  setTimeout(arguments.callee, 10);
}, 10);

setInterval(function(){
  /* Some long block of code... */}, 10);

這兩段程式碼乍看之下似乎在功能上等同,但它們不是。值得注意的是,setTimeout程式碼在前一次回呼執行後總是至少有10ms的延遲(它可能最終會更多,但絕不會少於10ms),而setInterval在這段長程式碼執行期間它都會嘗試每10ms執行一次回呼(譯者註:可理解為在這段長代碼執行期間,會每10ms新增一個任務進隊列,中間無間隔)。

我們在這裡學到了很多,讓我們回顧一下:

JavaScript引擎只有一個線程,迫使非同步事件排隊等待執行。
setTimeout並且setInterval它們在執行非同步程式碼方面有著根本的不同。
如果計時器被阻止立即執行,它將被延遲到下一個可能的執行點(這將超過所需的延遲)。
如果setInterval中回呼程式執行時間夠長(超過指定的延遲),則間隔可以無延遲地執行(譯者註:因為在一個回呼沒有運行完的時候就會再加入一個回調)。
所有這些都是用來了解JavaScript引擎的工作原理的非常重要的知識,尤其是發生的大量非同步事件的時候,為建立高級應用程式程式碼奠定了基礎。

相關推薦:

javascript 定時器工作原理

#關於JavaScript中計時器的原理解析

以上是詳細介紹JavaScript定時器的工作原理的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn