先来一个经典的题
setTimeout(function () {
console.log(1);
}, 0);
new Promise(function (a, b) {
console.log(2);
for (var i = 0; i < 10; i++) {
if (i == 9) a()
}
console.log(3)
}).then(function () {
console.log(4)
});
console.log(5);
function a() {
console.log(3)
}
正确输出顺序为:2,3,5,4,1;这里就要提到js的事件循环了,js是单线程的缺可以处理异步,就是因为Event Loop(事件循环)。
任务进入执行栈,会先判断是同步还是异步任务,同步任务会被加入主线程继续执行,而异步任务会被挂起,当异步任务有返回值时会被添加到事件队列,当主线程闲置时,主线程会去查找事件队列是否有任务,将排在第一位事件的回调放入执行栈,执行同步代码,如此反复,这个过程就被成为 事件循环。
- macro-task(宏任务):script,setTimeout,setInterval
- micro-task(微任务):Promise,process.nextTick
js的异步执行机制是这样的,不同类型的任务会进入不同的Event Queue,有宏任务的队列和微任务的队列。代码开始执行时,先执行宏任务,接着执行所有微任务,然后再执行宏任务....
- 运行到 settimeout,将其回调函数添加到宏任务;
- 运行到new promise,立即执行输出 ‘ 2 ’,执行for循环,进入if判断,执行a函数输出 '3' then回调添加到微任务;
- 运行到console,输出‘5’;
- 宏任务结束,检查微任务,发现then回调,输出‘4’
- 第二轮开始,发现宏任务settimeout的回调,输出‘1’
- 结束