1. 程式人生 > >JavaScript 執行機制:Event Loop

JavaScript 執行機制:Event Loop

JavaScript 是單執行緒語言。單執行緒就意味著需要排隊,前一個任務完成才能執行下一個任務。所以任務分為兩種,同步任務和非同步任務。

  • 同步任務指的是,在主執行緒上排隊執行的任務,只有前一個任務執行完畢,才能執行下一個任務。
  • 非同步任務指的是不進入主執行緒,而進入“任務佇列”的任務,只有任務佇列通知主執行緒,某個非同步任務可以執行了,該任務才會進入主執行緒執行。

不同的任務源會被分配到不同的 Task 佇列中,任務源可以分為 微任務(microtask)和 巨集任務(macrotask)。

  • 巨集任務:包括整體程式碼script,setTimeout,setInterval
  • 微任務:Promise.then(非new Promise),process.nextTick(node中)

非同步執行的執行機制如下:(同步執行可以視為沒有非同步任務的非同步執行)

  1. 所有同步任務都在主執行緒上執行,這屬於巨集任務,形成一個執行棧。先執行巨集任務在執行微任務
  2. 主執行緒之外,還存在一個任務佇列。非同步任務只要有了執行結果,就在任務佇列中放置一個事件。
  3. 執行棧中的所有同步任務執行完畢,系統就會讀取任務佇列,將對應的非同步任務放入執行棧,開始執行微任務
  4. 主執行緒不斷重複上面的第三步。

主執行緒叢任務佇列中讀取事件,這個過程是迴圈不斷的,所以這種執行機制又稱為 Event Loop(事件迴圈)

除了放置非同步任務的事件,任務佇列還可以放置定時事件。定時器功能主要由setTimeout()和setInterval()這兩個函式來完成,它們的內部執行機制完全一樣,區別在於前者指定的程式碼是一次性執行,後者則為反覆執行。

	console.log('1');
	setTimeout(function() {
	    console.log('2');
	    process.nextTick(function() {
	        console.log('3');
	    })
	    new Promise(function(resolve) {
	        console.
log('4'); resolve(); }).then(function() { console.log('5') }) }) 輸出: 1 2 4 3 5 1. 巨集任務同步程式碼console.log('1'),不多說 2. setTimeout,加入巨集任務Event Queue,沒有發現微任務,第一輪事件迴圈走完 3. 第二輪事件迴圈開始,先執行巨集任務,從巨集任務Event Queue中獨取出setTimeout的回撥函式 4. 同步程式碼console.log('2'),發現process.nextTick,加入微任務Event Queue 5. new Promise,同步執行console.log('4'),發現then,加入微任務Event Queue 6. 巨集任務執行完畢,接下來執行微任務,先執行process.nextTick,然後執行Promise.then 7. 微任務執行完畢,第二輪事件迴圈走完,沒有發現巨集任務,事件迴圈結束