Event Loop,事件環,線程進程。這些概念對初識前端的同窗來講可能會一頭霧水。並且運行js代碼的運行環境除了瀏覽器還有node。所以不一樣環境處理Event Loop又變得不一樣,十分容易混淆。若是你有這樣的疑問。下文將給你一個清晰的解釋。javascript
首先咱們簡化一下概念,把進程,線程,事件環,這些概念梳理一下。清晰了概念後面用到的時候就會有共鳴。html
拿出在教科書裏的概念:前端
一、調度:線程做爲調度和分配的基本單位,進程做爲擁有資源的基本單位;java
二、併發性:不只進程之間能夠併發執行,同一個進程的多個線程之間也可併發執行;node
三、擁有資源:進程是擁有資源的一個獨立單位,線程不擁有系統資源,但能夠訪問隸屬於進程的資源;git
四、系統開銷:在建立或撤消進程時,因爲系統都要爲之分配和回收資源,致使系統的開銷明顯大於建立或撤消線程時的開銷。es6
進程和線程的關係:github
接下來看一下瀏覽器引擎(進程)中包含哪些線程chrome
注意
:UI渲染線程與JS引擎線程是互斥的,當JS引擎執行時GUI線程會被掛起(至關於被凍結了),UI更新會被保存在一個隊列中等到JS引擎空閒時當即被執行。後端
一樣注意
:UI渲染線程與JS引擎線程是互斥的,因此若是JS執行的時間過長,這樣就會形成頁面的渲染不連貫,致使頁面渲染加載阻塞。
注意
:因爲JS的單線程關係,因此這些待處理隊列中的事件都得排隊等待JS引擎處理(當JS引擎空閒時纔會去執行)
注意
:W3C在HTML標準中規定,規定要求setTimeout中低於4ms的時間間隔算爲4ms。
以上線程,每一個拿出來均可以詳細的說上一篇。Event Loop涉及到的JS引擎的一些運行機制的分析。咱們能夠將這些線程理解爲,
setTimeout(function(){
console.log(0)
},500)
setTimeout(function(){
console.log(1)
},1000)
setTimeout(function(){
console.log(2)
},2000)
for(;;){
}
複製代碼
上面這段代碼用於不會有輸出,同步代碼死循環阻塞了執行棧。雖然定時後回調加入執行隊列,可是異永遠不會執行。
題目二:
setTimeout(function(){
console.log('setTimeout1');
Promise.resolve().then(()=>{
console.log('then1');
});
},0)
Promise.resolve().then(()=>{
console.log('then2');
Promise.resolve().then(()=>{
console.log('then3');
})
setTimeout(function(){
console.log('setTimeout2');
},0)
})
複製代碼
答案:then2 then3 setTimeout1 then1 setTimeout2
首先在題目中出現了es6的promise,他的出現讓原來咱們理解的__事件環產生了一些不一樣__。 爲何呢?由於Promise裏有了一個一個新的概念:microtask 此時JS中分爲__兩種任務類型__:macrotask和microtask,在ECMAScript中,microtask稱爲jobs,macrotask可稱爲task
首先說明,是以__瀏覽器爲處理環境__下的執行邏輯 瀏覽器環境下的微任務和宏任務有哪些 宏任務:setTimeout setImmediate MessageChannel 微任務:Promise.then MutationObserver
記住兩點:
而後題目入手分析宏任務和微任務的執行
Node.js 是一個基於 Chrome V8 引擎的 JavaScript 運行環境。他的目標就是解析js代碼,讓他能運行起來。
和瀏覽器環境下相似,他有一個解析js的主線程,其餘線程做爲輔助,可是由於不涉及操做dom,ui線程就不存在了。(各個線程的概念參考瀏覽器環境下的線程)
單線程在瀏覽器運行環境中的弊端體如今阻塞頁面執行。
那麼node做爲後端服務,單線程有什麼利弊?
優勢:
事件環的總體仍是不變的,執行棧,消息隊列,api。不一樣的是,node下的消息隊列有所不一樣
從一個題目入手感覺一下node環境和瀏覽器環境下的不一樣
setTimeout(() => {
console.log('timeout1');
Promise.resolve().then(() => {
console.log('promise');
});
}, 0)
setTimeout(() => {
console.log('timeout2');
}, 0)
複製代碼
瀏覽器下的結果:timeout1 promise timeout2
node下的結果:timout1 timeout2 promise
node環境下的微任務和宏任務有哪些 宏任務:setTimeout setImmediate 微任務:Promise.then process.nextTick
題目三能夠很好的分析node環境下的任務執行 node環境下運行流程
注意
:一樣是微任務,process.nextTick,優於promise.then先執行
Promise.resolve().then(() => {
console.log('then')
})
process.nextTick(() => {
console.log('nextTick')
});
//nextTick then
複製代碼
注意
:一樣是宏任務,setTimeout和setImediate執行的前後順序是不肯定的,依賴於執行棧執行的速度。
setImmediate(function () {
console.log('setImmediate')
});
setTimeout(function () {
console.log('setTimeout')
}, 0); // ->4
複製代碼
let fs = require('fs');
fs.readFile('./gitignore', function () { // io的下一個事件隊列是check階段
setImmediate(function () {
console.log('setImmediate')
});
setTimeout(function () {
console.log('setTimeout')
}, 0); // ->4
})
複製代碼
給個提示,讀文件是io操做,io執行以後首先要check,check以後或沒有check內容再去檢查定時隊列。 那麼結果就留給你們自行分析了。
但願這篇文章能給初識js的你一個清晰的大框,也是梳理我本身的知識。可能我理解的也很粗淺,有錯誤的地方,但願你們幫忙指正。