1. 程式人生 > 程式設計 >JS事件迴圈機制event loop巨集任務微任務原理解析

JS事件迴圈機制event loop巨集任務微任務原理解析

首先看一段程式碼

async function (){
		await f2()
		console.log('f1')
	}

	async function f2(){
		console.log('f2')
	}
	
	console.log('正常1')
	f1()
	setTimeout(()=>{
		console.log('定時器')
	})
	console.log('正常2')

正確的列印順序應該是:正常1,f2 ,正常2,f1,定時器

為什麼會出現這樣列印順序呢

首先javascript是一門單執行緒語言,在最新的HTML5中提出了Web-Worker,但javascript是單執行緒這一核心仍未改變。既然js是單執行緒,那就像只有一個視窗的銀行,客戶需要排隊一個一個辦理業務,同理js任務也要一個一個順序執行。如果一個任務耗時過長,那麼後一個任務也必須等著。所以就出現了同步任務和非同步任務。

概念

除了廣義的同步任務和非同步任務,對任務可以進行更精細的區分

  • macro-task(巨集任務):包括整體程式碼script,setTimeout,setInterval
  • micro-task(微任務):Promise,process.nextTick

巨集任務:瀏覽器為了能夠使得JS內部task與DOM任務能夠有序的執行,會在一個task執行結束後,在下一個 task 執行開始前,對頁面進行重新渲染 (task->渲染->task->…)

滑鼠點選會觸發一個事件回撥,需要執行一個巨集任務,然後解析HTMl

微任務:微任務通常來說就是需要在當前 同步任務 執行結束後立即執行的任務,比如對一系列動作做出反饋,或者是需要非同步的執行任務而又不需要分配一個新的任務,這樣便可以減小一點效能的開銷。

既然我們清楚了概念,我們再看一遍程式碼

async function (){
		await f2()
		console.log('f1')
	}

	async function f2(){
		console.log('f2')
	}
	
	console.log('正常1')
	f1()
	setTimeout(()=>{
		console.log('定時器')
	})
	console.log('正常2')

執行順序

首先我們進行正常的同步流程,打印出‘正常1',接下來執行f1()函式,await後面的函式f2()會立即執行,所以會列印'f2',繼續執行同步程式碼列印‘正常2',至此同步任務全部結束,開始執行非同步任務微任務,await f2()等待f2()方法執行完之後打印出f1,最後執行巨集任務setTimeout列印‘定時器'

這就是為什麼‘正常1',正常2'會列印在‘f1'之前,因為所有微任務執行的時候,當前執行棧的程式碼必須已經執行完畢。‘f2','f1'會列印在‘定時器'之前是因為所有微任務總會在下一個巨集任務之前全部執行完畢

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。