js是單執行緒的,為什么可以執行異步操作呢?
這歸結與瀏覽器(js的宿主環境)通過某種方式使得js具備了異步的屬性,
區分行程和執行緒:
行程:正在運行中的應用程式,每個行程都自己獨立的記憶體空間,例如:打開的瀏覽器就是一個行程,
執行緒:行程的子集,是獨立的,執行緒在共享的記憶體空間中運行,
瀏覽器是多行程的,如下圖:

并且每打開一個頁面就創建了一個獨立的行程,行程內有自己的多執行緒,如果瀏覽器是單行程的,那么某個頁面崩了,就會影響整個瀏覽器,
瀏覽器有哪些行程:
1.Browser(瀏覽器):瀏覽器的主行程(負責協調,主控)只有一個,作用有:
- 負責瀏覽器界面顯示,與用戶互動,如前進,后退等
- 負責各個頁面的管理,創建和銷毀其他行程
- 將Renderer(渲染器)行程得到的記憶體中的Bitmap,繪制到用戶界面上
- 網路資源的管理,下載等
2.第三方插件行程:每種型別的插件對應一個行程,僅當使用該插件時才創建
3.GPU行程:最多一個,用于3D繪制等
4.瀏覽器渲染行程(瀏覽器內核)(Renderer(渲染器),內部是多執行緒的)默認每個Tab頁面一個行程,互不影響,主要作用 :頁面渲染,腳本執行,事件處理等
瀏覽器渲染行程(瀏覽器內核)包含的執行緒:
1. GUI渲染執行緒
? 負責渲染瀏覽器界面,決議HTML,CSS,構建DOM樹和RenderObject樹,布局和繪制等,
? 當界面需要重繪(Repaint)或由于某種操作引發回流(reflow)時,該執行緒就會執行
? 注意,GUI渲染執行緒與JS引擎執行緒是互斥的,當JS引擎執行時GUI執行緒會被掛起(相當于被凍結了),GUI更新會被保存在一個佇列中等到JS引擎空閑時立即被執行,
2. JS引擎執行緒(
“JavaScript 引擎”通常被稱作一種 虛擬機,也稱為JS內核,負責處理Javascript腳本程式,(例如V8引擎)
? JS引擎執行緒負責決議Javascript腳本,運行代碼,
? JS引擎一直等待著任務佇列中任務的到來,然后加以處理,一個Tab頁(renderer行程)中無論什么時候都只有一個JS執行緒在運行JS程式
? 同樣注意,GUI渲染執行緒與JS引擎執行緒是互斥的,所以如果JS執行的時間過長,這樣就會造成頁面的渲染不連貫,導致頁面渲染加載阻塞,
3. 事件觸發執行緒
? 歸屬于瀏覽器而不是JS引擎,用來控制事件回圈(可以理解,JS引擎自己都忙不過來,需要瀏覽器另開執行緒協助)
? 當JS引擎執行代碼塊如setTimeOut時(也可來自瀏覽器內核的其他執行緒,如滑鼠點擊、AJAX異步請求等),會將對應任務添加到事件執行緒中
? 當對應的事件符合觸發條件被觸發時,該執行緒會把事件添加到待處理佇列的隊尾,等待JS引擎的處理
? 注意,由于JS的單執行緒關系,所以這些待處理佇列中的事件都得排隊等待JS引擎處理(當JS引擎空閑時才會去執行)
4. 定時觸發器執行緒
? 傳說中的setInterval與setTimeout所在執行緒
? 瀏覽器定時計數器并不是由JavaScript引擎計數的,(因為JavaScript引擎是單執行緒的, 如果處于阻塞執行緒狀態就會影響記計時的準確)
? 因此通過單獨執行緒來計時并觸發定時(計時完畢后,添加到事件佇列中,等待JS引擎空閑后執行)
? 注意,W3C在HTML標準中規定,規定要求setTimeout中低于4ms的時間間隔算為4ms,
5. 異步http請求執行緒
? 在XMLHttpRequest在連接后是通過瀏覽器新開一個執行緒請求
? 將檢測到狀態變更時,如果設定有回呼函式,異步執行緒就產生狀態變更事件,將這個回呼再放入事件佇列中,再由JavaScript引擎執行,
GUI渲染執行緒與JS引擎執行緒互斥:
由于JavaScript是可操縱DOM的,如果在修改這些元素屬性同時渲染界面(即JS執行緒和UI執行緒同時運行),那么渲染執行緒前后獲得的元素資料就可能不一致了,因此為了防止渲染出現不可預期的結果,瀏覽器設定GUI渲染執行緒與JS引擎為互斥的關系,當JS引擎執行時GUI執行緒會被掛起,GUI更新則會被保存在一個佇列中等到JS引擎執行緒空閑時立即被執行,
js執行機制:js是單執行緒的,每當執行函式就把函式推入堆疊中,但有異步的操作就讓瀏覽器的執行緒(webAPI)去處理,處理完放到任務佇列里,當主執行緒(執行堆疊)執行完畢時,如果任務佇列里有任務,就執行,
這也就是為什么下面代碼會先輸出b,然后是a的原因,settimeout的函式會放到任務佇列中,而console.log('b')是主執行緒,
setTimeout(() => {
console.log('a');
}, 0);
console.log('b');
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/167845.html
標籤:JavaScript
上一篇:在vue組件中設定定時器和清除定時器
下一篇:echarts關系圖圓心顏色漸變