javascript event loop(1)
這篇文章學習 jake 一次分享,首先感謝 jake 的分享,當然我們都是學習別人,但是我個人並不是簡單地傳遞或翻譯他人內容,而是融入了自己思想,可能是不對的,將一些自己學過過程中的遇到問題給大家分享,以便大家更好地理解作者分享的內容。
看到下面的程式碼,大家可能會有顧慮這樣寫,el 會不會在螢幕上有一閃而過的效果

我通過程式碼進行嘗試,並沒有您顧慮那種情況,因為在 javascript 中並沒 race condition 的問題


在 web 頁面有一個主執行緒,之所以叫主執行緒,是因為載入檔案(css 或 javascript)、以及 javascript 的執行和頁面渲染,dom 所有這些一切都是發生在這個執行緒中。

這樣就表示以上所有動作都是有一定順序,因為他們都發生一個執行緒裡。我們無法用同時編輯和修改一個 DOM ,所以也就不存在 race condition 的問題了。但是如何某一個動作佔用主執行緒時間過長,所謂長時間一般在 200 毫秒以上,這樣就會影響其他動作,在這段時間內阻止使用者互動,造成不好的使用者體驗。
但是我們一些耗時例如網路請求,也些使用者操作、解碼和編碼,這些都會執行在主執行緒以外的執行緒,當結束後會將資訊返回到主執行緒。這就是今天主題 the event loop,這裡我就不翻譯這個詞,保持原滋原味吧。
setTimeout(callback,ms) 想必大家都用過吧,引數位置看起來有點彆扭,不過今天我們拋開這個,探究一下方法背後究竟發生了什麼。

當然我們不想讓這個方法佔據主執行緒那麼多時間,所以我們這個方法是並行於主線執行的

但是如果並行執行的話,那麼我們希望 callback 方法是返回到主執行緒進行執行的。但是問題來了這些非同步操作當他們返回主執行緒對 dom 進行操作,會不會引起 race condition 呢?
為了解決這個問題,引入了任務佇列,這些任務會有序地返回到主執行緒進行執行,
當你點選滑鼠,那麼如何從系統操作來到 javascript 呢?這也是進入任務佇列
任務佇列
任務佇列是 event loop 一部分,也是歷史悠久了。下圖我們通過圖形的形式來生動地展示 event loop 是如何工作的。
我們發現了這裡有一個小門,當有任務時候小門就會開啟,然後去執行任務。讓瀏覽器通知 event loop ,hey 我們有些任務要做,就會開啟小門

下面我們建立兩個 setTimeout 指定相同延時時間然後進行列印來看效果



當執行這兩個方法會並行於主執行緒進行執行,然後回到主線,執行順序是根據任務佇列順序決定。

瀏覽器通知 event loop 有任務要回到主執行緒執行, 我有兩個任務在任務佇列中,這樣 event loop 會按順序依次執行兩個任務


渲染步驟
這是瀏覽是如何更新螢幕輸出的,分步渲染是 event loop 另一個小門,這裡首先查詢計算所有 css 然後將其應用到每一個元素上。

然後(Layout)是佈局,根據渲染樹(dom 的結構)來放置每個元素到螢幕上其該有的位置。

最後也就是根據樣式和位置資訊生產 pixel 資料,每一個畫素的顏色以及透明度,然後根據這些資料進行繪製。


如果我們點選這個按鈕,整個 JavaScript 世界就停止在您點選這一刻,無法進行任何操作。

為什麼會這樣呢?當您點選按鈕,瀏覽器通知 event loop 這一個任務需要你執行,event loop 就會立即執行任務,

不過這是無限任務,幾毫秒後瀏覽器還想讓 event loop 去做一些其他類似更新介面工作。

不過這是 event loop 沒有完成手頭上工作是無法進行下一項工作的。


回到開始問題,我們擔心會有閃爍效果,不過事實證明並沒有閃爍效果,這是因為這些程式碼是在瀏覽器進行下一個階段分步渲染前已經被執行完畢了。event loop 會確保在進行下一次渲染前結束任務。

當迴圈阻塞了渲染,那麼我們將loop放置到 setTimeout 中,然後在 setTimeout 繼續執行 loop 以達到迴圈效果。

這樣再次點選按鈕就不會阻塞渲染了,我們依舊可以與瀏覽器進行互動操作。


這樣每一次執行完任務後就回到 event loop 執行渲染,

然後再去執行 loop 生產的下一個任務。

