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);