js線程機制

前幾日寫了一篇文章,介紹了js阻塞頁面加載的問題。當時是通過例子來驗證的。今天,我介紹一下瀏覽器內核,從原理上介紹一下js阻塞頁面加載的原因。


瀏覽器的內核是多線程的,它們在內核制控下相互配合以保持同步,一個瀏覽器至少實現三個常駐線程:javascript引擎線程,GUI渲染線程,瀏覽器事件觸發線程。

1.        javascript引擎是基於事件驅動單線程執行的,JS引擎一直等待着任務隊列中任務的到來,然後加以處理,瀏覽器無論什麼時候都只有一個JS線程在運行JS程序

2.        GUI渲染線程負責渲染瀏覽器界面,當界面需要重繪(Repaint)或由於某種操作引發迴流(reflow),該線程就會執行。但需要注意 GUI渲染線程與JS引擎是互斥的,當JS引擎執行時GUI線程會被掛起,GUI更新會被保存在一個隊列中等到JS引擎空閒時立即被執行。

3.        事件觸發線程,當一個事件被觸發時該線程會把事件添加到待處理隊列的隊尾,等待JS引擎的處理。這些事件可來自JavaScript引擎當前執行的代碼塊如setTimeOut、也可來自瀏覽器內核的其他線程如鼠標點擊、AJAX異步請求等,但由於JS的單線程關係所有這些事件都得排隊等待JS引擎處理。

 

由上文藍色標註的文字可以知道,當瀏覽器在執行JS程序的時候,GUI渲染線程會被保存在一個隊列中,直到JS程序執行完成。這樣就造成了頁面的渲染,就是所說的JS阻塞頁面加載問題。

 

很多同學朋友搞不清楚,既然說JavaScript是單線程運行的,那麼XMLHttpRequest在連接後是否真的異步?

其實請求確實是異步的,不過這請求是由瀏覽器新開一個線程請求(參見上圖),當請求的狀態變更時,如果先前已設置回調,這異步線程就產生狀態變更事件放到 JavaScript引擎的處理隊列中等待處理,當任務被處理時,JavaScript引擎始終是單線程運行回調函數,具體點即還是單線程運行 onreadystatechange所設置的函數.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章