瀏覽器中JavaScript語言的一大特色就是單線程,也就是說,同一個時間只能作一件事。js同步執行。單線程就意味着,全部任務須要排隊,前一個任務結束,纔會執行後一個任務。瀏覽器中的Event Loop
簡單來講是,瀏覽器中js運行的順序,誰先誰後。html
在瞭解eventloop以前,先來看一下。瀏覽器的機制node
(1)全部同步任務都在主線程上執行,造成一個執行棧(execution context stack)。git
(2)主線程以外,還存在一個"任務隊列"(task queue)。只要異步任務有了運行結果,就在"任務隊列"之中放置一個事件。github
(3)一旦"執行棧"中的全部同步任務執行完畢,系統就會讀取"任務隊列",看看裏面有哪些事件。那些對應的異步任務,因而結束等待狀態,進入執行棧,開始執行。promise
(4)主線程不斷重複上面的第三步。瀏覽器
主線程從"任務隊列"中讀取事件,這個過程是循環不斷的,因此整個的這種運行機制又稱爲Event Loop(事件循環)。bash
棧: 先進後出, 異步
隊列:先進先出。函數
看上圖。主線程運行的時候,產生堆(heap)和棧(stack),棧中的代碼調用各類外部API,它們在"任務隊列"中加入各類事件(click,load,done)。只要棧中的代碼執行完畢,主線程就會去讀取"任務隊列",依次執行那些事件所對應的回調函數。oop
Node.js也是單線程的Event Loop,可是它的運行機制不一樣於瀏覽器環境。
(1)V8引擎解析JavaScript腳本。
(2)解析後的代碼,調用Node API。
(3)libuv庫負責Node API的執行。它將不一樣的任務分配給不一樣的線程,造成一個Event Loop(事件循環),以異步的方式將任務的執行結果返回給V8引擎。
(4)V8引擎再將結果返回給用戶。
好了,如今看下面的例子,在瀏覽器中,會打印出什麼?
瀏覽器中,
console.log(1);console.log(2);setTimeout(function(){ console.log('setTimeout1') Promise.resolve().then(function(){ console.log('promise') });})setTimeout(function(){ console.log('setTimeout2');});複製代碼
先走微任務,再走宏任務。
而在node中。下面是運行結果,
12setTimeout1setTimeout2promise複製代碼
最後總結:
微任務有:
then nextTick ( messageChannel mutationObersve)複製代碼
宏任務中有:
setTimeout setInterval setImmediate複製代碼