瀏覽器中JavaScript語言的一大特點就是單執行緒,也就是說,同一個時間只能做一件事。js同步執行。單執行緒就意味著,所有任務需要排隊,前一個任務結束,才會執行後一個任務。瀏覽器中的Event Loop
簡單來說是,瀏覽器中js執行的順序,誰先誰後。
在瞭解eventloop之前,先來看一下。瀏覽器的機制
(1)所有同步任務都在主執行緒上執行,形成一個執行棧(execution context stack)。
(2)主執行緒之外,還存在一個"任務佇列"(task queue)。只要非同步任務有了執行結果,就在"任務佇列"之中放置一個事件。
(3)一旦"執行棧"中的所有同步任務執行完畢,系統就會讀取"任務佇列",看看裡面有哪些事件。那些對應的非同步任務,於是結束等待狀態,進入執行棧,開始執行。
(4)主執行緒不斷重複上面的第三步。
主執行緒從"任務佇列"中讀取事件,這個過程是迴圈不斷的,所以整個的這種執行機制又稱為Event Loop(事件迴圈)。
棧: 先進後出,
佇列:先進先出。
看上圖。主執行緒執行的時候,產生堆(heap)和棧(stack),棧中的程式碼呼叫各種外部API,它們在"任務佇列"中加入各種事件(click,load,done)。只要棧中的程式碼執行完畢,主執行緒就會去讀取"任務佇列",依次執行那些事件所對應的回撥函式。
// 瀏覽器中 先執行當前棧 執行完走微任務 走事件佇列裡的內容(拿出一個)放到棧裡執行。
Node系統
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複製程式碼