將本身讀到的比較好的文章分享出來,你們互相學習,各位大佬有好的文章也能夠留個連接互相學習,萬分感謝!
關於線程與進程的關係能夠用下面的圖進行說明:ios
1:n
的關係。而官方的說法是:git
CPU
資源分配的最小單位。CPU
調度的最小單位。從更直觀的例子來看,能夠打開任務管理器查看,第一個 tab
即是進程列表,每個進程佔有的 CPU
資源和內存資源的比例很直觀的展現出來。github
初學計算機語言的時候,不管是 C、C++
仍是 JAVA
,都是支持多線程,恰恰 JavaScript
是單線程,不支持多線程,這也跟 JavaScript
的做用有關,都知道 JavaScript
是主要運行在瀏覽器的腳本語言,最終操做的是頁面的 DOM
結構,當兩個 JavaScript
腳本同時修改頁面的同一個 DOM
節點時,瀏覽器該執行哪一個呢?因此當時設計 JavaScript
時,便要求當前修改操做完成後方可進行下一步修改操做。ajax
一樣咱們打開瀏覽器的任務管理器,如下圖爲例:瀏覽器
瀏覽器的每個 tab
頁都是一個進程,有對應的內存佔用空間、 CPU
使用量以及進程ID。 新打開一個 tab
頁時,都會新建一個進程,因此就有一個 tab
頁對應一個進程的說法,可是這種說法又是錯誤的,由於瀏覽器有本身的優化機制,當咱們打開多個空白的 tab
頁時,瀏覽器會將這多個空白頁的進程合併爲一個,從而減小了進程的數量個數。多線程
瀏覽器內核中有多個進程在同步工做,今天涉及到的瀏覽器的進程主要包括如下進程:異步
主進程,主要負責頁面管理以及管理其餘進程的建立和銷燬等,常駐的線程有:函數
- GUI渲染線程
- JS引擎線程
- 事件觸發線程
- 定時器觸發線程
- HTTP請求線程
GUI渲染線程oop
- 主要負責頁面的渲染,解析HTML、CSS,構建DOM樹,佈局和繪製等。
- 當界面須要重繪或者因爲某種操做引起迴流時,將執行該線程。
- 該線程與JS引擎線程互斥,當執行JS引擎線程時,GUI渲染會被掛起,當任務隊列空閒時,JS引擎纔會去執行GUI渲染。
JS引擎線程佈局
- 該線程固然是主要負責處理
JavaScript
腳本,執行代碼。- 也是主要負責執行準備好待執行的事件,即定時器計數結束,或者異步請求成功並正確返回時,將依次進入任務隊列,等待
JS引擎線程
的執行。- 固然,該線程與
GUI渲染線程
互斥,當JS引擎線程
執行JavaScript
腳本時間過長,將致使頁面渲染的阻塞。事件觸發線程
- 主要負責將準備好的事件交給
JS引擎線程
執行。- 好比
setTimeout
定時器計數結束,ajax
等異步請求成功並觸發回調函數,或者用戶觸發點擊事件時,該線程會將整裝待發的事件依次加入到任務隊列的隊尾,等待JS引擎線程
的執行。定時器觸發線程
- 顧名思義,負責執行異步定時器一類的函數的線程,如:
setTimeout,setInterval
。- 主線程依次執行代碼時,遇到定時器,會將定時器交給該線程處理,當計數完畢後,事件觸發線程會將計數完畢後的事件加入到任務隊列的尾部,等待JS引擎線程執行。
HTTP請求線程
- 顧名思義,負責執行異步請求一類的函數的線程,如:
Promise,anxios,ajax
等。- 主線程依次執行代碼時,遇到異步請求,會將函數交給該線程處理,當監聽到狀態碼變動,若是有回調函數,事件觸發線程會將回調函數加入到任務隊列的尾部,等待JS引擎線程執行。
多個線程之間配合工做,各司其職。
瀏覽器渲染進程(瀏覽器內核),主要負責頁面的渲染、JS執行以及事件的循環。
console.log()
打印一條日誌、聲明一個變量或者執行一次加法操做等。常見的異步操做:
下圖給出了同步任務與異步任務的執行流程:
那麼任務究竟是如何入棧和出棧的呢?能夠用一小段代碼進行解釋。
如下面的代碼爲例:
console.log(1); function fn1(){ console.log(2); } function fn2(){ console.log(3); fn1(); } setTimeout(function(){ console.log(4); }, 2000); fn2(); console.log(5);
因此上面代碼運行的結果爲:1,3,2,5,4。
異步任務分爲宏任務和微任務,宏任務隊列能夠有多個,微任務隊列只有一個。
宏任務和微任務的執行方式在瀏覽器和 Node
中有差別。
script
(全局任務),setTimeout
,setInterval
,setImmediate
,I/O
,UI rendering
process.nextTick
,Promise.then()
,Object.observe
,MutationObserver
在微任務中 process.nextTick 優先級高於Promise
當一個異步任務入棧時,主線程判斷該任務爲異步任務,並把該任務交給異步處理模塊處理,當異步處理模塊處理完打到觸發條件時,根據任務的類型,將回調函數壓入任務隊列。
因此上圖的任務隊列能夠繼續細化一下:
那麼當棧爲空時,宏任務和微任務的執行機制又是什麼呢?
到這裏,除了上面的問題,咱們已經把事件循環的最基本的處理方式搞清楚了,但具體到異步任務中的宏任務和微任務,尚未弄明白。咱們能夠先順一遍執行機制:
script
開始,任務依次進入棧中,被主線程執行,執行完後出棧。到這問題就來了,當異步任務進入棧執行時,是宏任務仍是微任務呢?
script
,而全局任務屬於宏任務,因此當棧爲空,同步任務任務執行完畢時,會先執行微任務隊列裏的任務。回到最開始的那段代碼,如今咱們能夠一步一步的看一下執行順序。
console.log(1); setTimeout(function(){ console.log(2); }, 0); setTimeout(function(){ console.log(3) },2000) console.log(4);
1
,setTimeout
,交給異步處理模塊,咱們暫且先記爲 setTimeout1
,setTimeout
,交給異步處理模塊,咱們暫且先記爲 setTimeout2
,4
,setTimeout1
的回調函數,由於定時器的等待時間爲 0
秒,因此會直接輸出 2
,可是 W3C
在 HTML
標準中規定,規定要求 setTimeout
中低於 4ms
的時間間隔算爲 4ms
,setTimeout1
執行完時, setTimeout2
的等待時間並未結束,因此在 2秒
後打印日誌 3
,實際上並未等待2秒。下面咱們能夠再看一個實例:
setTimeout(function(){ console.log(1); Promise.resolve().then(function(){ console.log(2) }) },0) setTimeout(function(){ console.log(3) },0) Promise.resolve().then(function(){ console.log(4) }); console.log(5)
當代碼中遇到了異步請求的事件,又該如何執行,根據上面總結的執行機制,又該獲得什麼樣的結果?
第一輪循環
setTimeout
,交給異步處理模塊,咱們暫且先記爲 setTimeout1
,因爲等待時間爲 0
,直接加入宏任務隊列。setTimeout
,交給異步處理模塊,咱們暫且先記爲 setTimeout2
,一樣直接加入宏任務隊列。then()
,加入微任務隊列。5
。第一輪循環結束後,能夠畫出下圖:
第二輪循環
then()
方法,輸出 4
,此時微任務隊列爲空。
setTimeout1
。1
,又遇到微任務 then()
,加入微任務隊列。第二輪循環結束。
第三輪循環
then()
方法,輸出 2
,此時微任務隊列爲空。
setTimeout2
。3
。第三輪循環結束,執行完畢。
最後咱們是咱們的boss,歡迎你們在評論區留言寫出本身心中的那個正確答案。
console.log(1); setTimeout(function(){ console.log(2); new Promise(function(resolve, reject){ console.log(3); resolve(); }).then(function(){ console.log(4); }) }) new Promise(function(resolve, reject){ console.log(5); resolve(); }).then(function(){ console.log(6); }) setTimeout(function(){ console.log(7) }) setTimeout(function(){ console.log(8); new Promise(function(resolve, reject){ console.log(9); resolve(); }).then(function(){ console.log(10); }) }) new Promise(function(resolve){ console.log(11); resolve(); }).then(function(){ console.log(12) }) console.log(13)
github地址:https://github.com/ABCDdouyaer/a_article_per_day/tree/master/0001
原文連接:https://mp.weixin.qq.com/s/9_hZX_xWSr3Gd1X_2_WOsA