共計 3771 個字符,預計需要花費 10 分鐘才能閱讀完成。
本篇內容主要講解“setTimeout 和 setInterval 怎么理解”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓丸趣 TV 小編來帶大家學習“setTimeout 和 setInterval 怎么理解”吧!
javascript 線程解釋(setTimeout,setInterval 你不知道的事)
JavaScript 的 setTimeout 與 setInterval 是兩個很容易欺騙別人感情的方法, 因為我們開始常常以為調用了就會按既定的方式執行, 我想不少人都深有同感, 例如
setTimeout(function(){;
setInterval(callbackFunction , 100);
認為 setTimeout 中的問候方法會立即被執行, 因為這并不是憑空而說, 而是 JavaScript API 文檔明確定義第二個參數意義為隔多少毫秒后, 回調方法就會被執行. 這里設成 0 毫秒, 理所當然就立即被執行了.
同理對 setInterval 的 callbackFunction 方法每間隔 100 毫秒就立即被執行深信不疑!
但隨著 JavaScript 應用開發經驗不斷的增加和豐富, 有一天你發現了一段怪異的代碼而百思不得其解:
div.onclick = function(){
setTimeout(function(){document.getElementByIdx_x(’inputField’).focus();}, 0);
};
既然是 0 毫秒后執行, 那么還用 setTimeout 干什么, 此刻, 堅定的信念已開始動搖.
直到最后某一天 , 你不小心寫了一段糟糕的代碼:
setTimeout(function(){while(true){}} , 100);
setTimeout(function(){;
setInterval(callbackFunction , 200);
第一行代碼進入了死循環, 但不久你就會發現, 第二, 第三行并不是預料中的事情,alert 問候未見出現,callbacKFunction 也杳無音訊!
這時你徹底迷惘了, 這種情景是難以接受的, 因為改變長久以來既定的認知去接受新思想的過程是痛苦的, 但情事實擺在眼前, 對 JavaScript 真理的探求并不會因為痛苦而停止, 下面讓我們來展開 JavaScript 線程和定時器探索之旅!
拔開云霧見月明
出現上面所有誤區的最主要一個原因是: 潛意識中認為,JavaScript 引擎有多個線程在執行,JavaScript 的定時器回調函數是異步執行的.
而事實上的,JavaScript 使用了障眼法, 在多數時候騙過了我們的眼睛, 這里背光得澄清一個事實:
JavaScript 引擎是單線程運行的, 瀏覽器無論在什么時候都只且只有一個線程在運行 JavaScript 程序.
JavaScript 引擎用單線程運行也是有意義的, 單線程不必理會線程同步這些復雜的問題, 問題得到簡化.
那么單線程的 JavaScript 引擎是怎么配合瀏覽器內核處理這些定時器和響應瀏覽器事件的呢?
下面結合瀏覽器內核處理方式簡單說明.
瀏覽器內核實現允許多個線程異步執行, 這些線程在內核制控下相互配合以保持同步. 假如某一瀏覽器內核的實現至少有三個常駐線 程:javascript 引擎線程, 界面渲染線程, 瀏覽器事件觸發線程, 除些以外, 也有一些執行完就終止的線程, 如 Http 請求線程, 這些異步線程都會產 生不同的異步事件, 下面通過一個圖來闡明單線程的 JavaScript 引擎與另外那些線程是怎樣互動通信的. 雖然每個瀏覽器內核實現細節不同, 但這其中的 調用原理都是大同小異.
由圖可看出, 瀏覽器中的 JavaScript 引擎是基于事件驅動的, 這里的事件可看作是瀏覽器派給它的各種任務, 這些任務可以源自 JavaScript 引擎當前執行的代碼塊, 如調用 setTimeout 添加一個任務, 也可來自瀏覽器內核的其它線程, 如界面元素鼠標點擊事件, 定時觸發 器時間到達通知, 異步請求狀態變更通知等. 從代碼角度看來任務實體就是各種回調函數,JavaScript 引擎一直等待著任務隊列中任務的到來. 由于單線 程關系, 這些任務得進行排隊, 一個接著一個被引擎處理.
上圖 t1-t2..tn 表示不同的時間點,tn 下面對應的小方塊代表該時間點的任務, 假設現在是 t1 時刻, 引擎運行在 t1 對應的任務方塊代碼內, 在這個時間點內, 我們來描述一下瀏覽器內核其它線程的狀態.
t1 時刻:
GUI 渲染線程:
該線程負責渲染瀏覽器界面 HTML 元素, 當界面需要重繪 (Repaint) 或由于某種操作引發回流 (reflow) 時, 該線程就會執行. 本文雖然重 點解釋 JavaScript 定時機制, 但這時有必要說說渲染線程, 因為該線程與 JavaScript 引擎線程是互斥的, 這容易理解, 因為 JavaScript 腳本是可操縱 DOM 元素, 在修改這些元素屬性同時渲染界面, 那么渲染線程前后獲得的元素數據就可能不一致了.
在 JavaScript 引擎運行腳本期間, 瀏覽器渲染線程都是處于掛起狀態的, 也就是說被”凍結”了.
所以, 在腳本中執行對界面進行更新操作, 如添加結點, 刪除結點或改變結點的外觀等更新并不會立即體現出來, 這些操作將保存在一個隊列中, 待 JavaScript 引擎空閑時才有機會渲染出來.
GUI 事件觸發線程:
JavaScript 腳本的執行不影響 html 元素事件的觸發, 在 t1 時間段內, 首先是用戶點擊了一個鼠標鍵, 點擊被瀏覽器事件觸發線程捕捉后形成 一個鼠標點擊事件, 由圖可知, 對于 JavaScript 引擎線程來說, 這事件是由其它線程異步傳到任務隊列尾的, 由于引擎正在處理 t1 時的任務, 這個鼠標 點擊事件正在等待處理.
定時觸發線程:
注意這里的瀏覽器模型定時計數器并不是由 JavaScript 引擎計數的, 因為 JavaScript 引擎是單線程的, 如果處于阻塞線程狀態就計不了時, 它必須依賴外部來計時并觸發定時, 所以隊列中的定時事件也是異步事件.
由圖可知, 在這 t1 的時間段內, 繼鼠標點擊事件觸發后, 先前已設置的 setTimeout 定時也到達了, 此刻對 JavaScript 引擎來說, 定時觸發線程產生了一個異步定時事件并放到任務隊列中, 該事件被排到點擊事件回調之后, 等待處理.
同理, 還是在 t1 時間段內, 接下來某個 setInterval 定時器也被添加了, 由于是間隔定時, 在 t1 段內連續被觸發了兩次, 這兩個事件被排到隊尾等待處理.
可見, 假如時間段 t1 非常長, 遠大于 setInterval 的定時間隔, 那么定時觸發線程就會源源不斷的產生異步定時事件并放到任務隊列尾而不管它 們是否已被處理, 但一旦 t1 和最先的定時事件前面的任務已處理完, 這些排列中的定時事件就依次不間斷的被執行, 這是因為, 對于 JavaScript 引擎來 說, 在處理隊列中的各任務處理方式都是一樣的, 只是處理的次序不同而已.
t1 過后, 也就是說當前處理的任務已返回,JavaScript 引擎會檢查任務隊列, 發現當前隊列非空, 就取出 t2 下面對應的任務執行, 其它時間依此類推, 由此看來:
如果隊列非空, 引擎就從隊列頭取出一個任務, 直到該任務處理完, 即返回后引擎接著運行下一個任務, 在任務沒返回前隊列中的其它任務是沒法被執行的.
相信您現在已經很清楚 JavaScript 是否可多線程, 也了解理解 JavaScript 定時器運行機制了, 下面我們來對一些案例進行分析:
案例 1:setTimeout 與 setInterval
setTimeout(function(){
setTimeout(arguments.callee, 10);
}, 10);
setInterval(function(){
}, 10);
這兩段代碼看一起效果一樣, 其實非也, 第一段中回調函數內的 setTimeout 是 JavaScript 引擎執行后再設置新的 setTimeout 定時, 假定上一個回調處理完到下一個回調開始處理為一個時間間隔, 理論兩個 setTimeout 回調執行時間間隔 =10ms . 第二段自 setInterval 設置定時后, 定時觸發線程就會源源不斷的每隔十秒產生異步定時事件并放到任務隊列尾, 理論上兩個 setInterval 回調執行時間間隔 =10.
案例 2:ajax 異步請求是否真的異步?
很多同學朋友搞不清楚, 既然說 JavaScript 是單線程運行的, 那么 XMLHttpRequest 在連接后是否真的異步?
其實請求確實是異步的, 不過這請求是由瀏覽器新開一個線程請求(參見上圖), 當請求的狀態變更時, 如果先前已設置回調, 這異步線程就產生狀態變更事件放到 JavaScript 引擎的處理隊列中等待處理, 當任務被處理時,JavaScript 引擎始終是單線程運行回調函數, 具體點即還是單線程運行 onreadystatechange 所設置的函數.
個人補充:
setTimeout 或者 setInterval 的設置的時間參數的具體意思是:在參數指定的時間后將待執行方法放到執行隊列中,如果隊列中沒有其他方法等待,則回立即執行 setTimeout 指定的方法,因此有時給人好像是立即執行的假象。
到此,相信大家對“setTimeout 和 setInterval 怎么理解”有了更深的了解,不妨來實際操作一番吧!這里是丸趣 TV 網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!