你們都知道js是單線程的腳本語言,在同一時間,只能作同一件事,爲了協調事件、用戶交互、腳本、UI渲染和網絡處理等行爲,防止主線程阻塞,Event Loop方案應運而生...html
我的博客瞭解一下: obkoro1.com
js做爲主要運行在瀏覽器的腳本語言,js主要用途之一是操做DOM。面試
在js高程中舉過一個栗子,若是js同時有兩個線程,同時對同一個dom進行操做,這時瀏覽器應該聽哪一個線程的,如何判斷優先級?ajax
爲了不這種問題,js必須是一門單線程語言,而且在將來這個特色也不會改變。瀏覽器
由於js是單線程語言,當遇到異步任務(如ajax操做等)時,不可能一直等待異步完成,再繼續往下執行,在這期間瀏覽器是空閒狀態,顯而易見這會致使巨大的資源浪費。網絡
當執行某個函數、用戶點擊一次鼠標,Ajax完成,一個圖片加載完成等事件發生時,只要指定過回調函數,這些事件發生時就會進入執行棧隊列中,等待主線程讀取,遵循先進先出原則。dom
要明確的一點是,主線程跟執行棧是不一樣概念,主線程規定如今執行執行棧中的哪一個事件。異步
主線程循環:即主線程會不停的從執行棧中讀取事件,會執行完全部棧中的同步代碼。函數
當遇到一個異步事件後,並不會一直等待異步事件返回結果,而是會將這個事件掛在與執行棧不一樣的隊列中,咱們稱之爲任務隊列(Task Queue)。oop
當主線程將執行棧中全部的代碼執行完以後,主線程將會去查看任務隊列是否有任務。若是有,那麼主線程會依次執行那些任務隊列中的回調函數。post
不太理解的話,能夠運行一下下面的代碼,或者點擊一下這個demo
結果是當a、b、c函數都執行完成以後,三個setTimeout纔會依次執行。
let a = () => { setTimeout(() => { console.log('任務隊列函數1') }, 0) for (let i = 0; i < 5000; i++) { console.log('a的for循環') } console.log('a事件執行完') } let b = () => { setTimeout(() => { console.log('任務隊列函數2') }, 0) for (let i = 0; i < 5000; i++) { console.log('b的for循環') } console.log('b事件執行完') } let c = () => { setTimeout(() => { console.log('任務隊列函數3') }, 0) for (let i = 0; i < 5000; i++) { console.log('c的for循環') } console.log('c事件執行完') } a(); b(); c(); // 當a、b、c函數都執行完成以後,三個setTimeout纔會依次執行
異步任務分爲 宏任務(macrotask) 與 微任務 (microtask),不一樣的API註冊的任務會依次進入自身對應的隊列中,而後等待 Event Loop 將它們依次壓入執行棧中執行。
宏任務(macrotask)::
script(總體代碼)、setTimeout、setInterval、UI 渲染、 I/O、postMessage、 MessageChannel、setImmediate(Node.js 環境)
微任務(microtask):
Promise、 MutaionObserver、process.nextTick(Node.js環境)
Event Loop(事件循環)中,每一次循環稱爲 tick, 每一次tick的任務以下:
script
總體代碼),若是有則執行宏任務 > 全部微任務 > 宏任務,以下圖所示:
從上圖咱們能夠看出:
上面提到的demo結果能夠這麼理解:先執行script
宏任務,執行完了以後,再執行其餘兩個定時器宏任務。
下面這個題,不少人都應該看過/遇到過,從新來看會不會以爲清晰不少:
// 執行順序問題,考察頻率挺高的,先本身想答案** setTimeout(function () { console.log(1); }); new Promise(function(resolve,reject){ console.log(2) resolve(3) }).then(function(val){ console.log(val); }) console.log(4);
根據本文的解析,咱們能夠獲得:
script
同步代碼先執行new Promise中的console.log(2),then後面的不執行屬於微任務
而後執行console.log(4)
script
宏任務後,執行微任務,console.log(3),沒有其餘微任務了。根據本文的內容,能夠很輕鬆,且有理有據的猜出寫出正確答案:2,4,3,1.
相似上文的面試題還有不少,實則都大同小異,只要掌握了事件循環的機制,這些問題都會變得很簡單。
文章若有不正確的地方歡迎各位路過的大佬鞭策!但願你們看完能夠有所收穫,喜歡的話,趕忙點波訂閱關注/喜歡。
我的blog and 掘金我的主頁,如需轉載,請放上原文連接並署名。碼字不易,感謝支持!
若是喜歡本文的話,歡迎關注個人訂閱號,漫漫技術路,期待將來共同窗習成長。
以上2018.6.16