1. 程式人生 > >例項理解promise、macro-task、micro-task

例項理解promise、macro-task、micro-task

setTimeout(function(){
	console.log(1);
}, 0);
new Promise(function executor(resolve){
	console.log(2);
	for(var i=0; i<10000; i++){
		i == 999 && resolve();
	}
	console.log(3);
}).then(function(){
	console.log(4);
});
console.log(5);

先看結果:
在這裡插入圖片描述
js中事件執行主要分為兩種任務型別:macro-task(task)(巨集任務)、micro-task(Job queue)(微任務);

什麼會加入到task,什麼會加入到micro-task?
task:script(全域性任務),setTimeout,setInterval,setImmediate ,I/O,UI渲染等 ;
micro-task: promise,Object,observe,process.nextTick,MutationObserver等;(通俗來說是執行定時器、事件、ajax事件等操作時);

那麼執行順序是什麼樣的:
script先進入函式呼叫棧,繼續執行
–>遇到巨集任務時把巨集任務加入巨集任務執行佇列(但暫不執行),遇到微任務把微任務加入微任務執行佇列(但暫不執行),等到函式呼叫棧所有內容出棧後
–>去執行微任務佇列
–>然後再回頭執行巨集任務佇列
–>再進入函式呼叫棧,執行微任務佇列,再執行巨集任務佇列,直到巨集任務佇列執行完畢

注意
1、undefined是console.log(5);列印時輸出的(因為控制檯執行程式碼,會返回最後一句程式碼的返回值,即consol.log()的返回值,即undefined)
2、每一個事件迴圈(event loop)都有一個microtasks
3、new的物件立即執行,promise建構函式傳入的函式會在本次new 操作立刻執行
4、.then和setTimeout都是非同步操作,但優先順序不一樣,then()優先順序更高些,所以4比1先輸出

綜合以上,上述程式碼執行過程如下:

// 加入巨集任務佇列,第五輸出1
setTimeout(function(){
	console.log(1);
}, 0);
// new立即執行而且是promise(加入微任務佇列)
new Promise(function executor(resolve){
	// 第一,輸出2
	console.log(2);
	for(var i=0; i<10000; i++){
		i == 999 && resolve();
	}
	//第二, 輸出3
	console.log(3);
}).then(function(){        // promise中的then操作是放在執行棧,也就是主執行緒的最後,暫存,繼續往下走
	// 第四,輸出4
	console.log(4);
});
// 第三,輸出5
console.log(5);