持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第1天,点击查看活动详情
什么是 event loop?
-
虽然 js 是单线程的语言,但是在运行上存在
同步任务
和异步任务
,具体表现为执行顺序不相同,event loop 机制规定了 js 的执行顺序,使得 js 单线程运行时不会阻塞 -
Javascript 有一个主线程
main thread
和调用栈(执行栈)call-stack
和任务队列task queue
,所有的任务都会被放到调用栈等待主线程执行 -
同步任务会在调用栈中按照入栈顺序待主线程执行,异步任务的回调会在满足条件后被放入任务队列,主线程清空调用栈后会再去执行队列中的异步任务的回调
-
异步任务又分为
宏任务
与微任务
,而主线程从任务队列中取出一个宏任务并执行,执行完毕后会清空队列中的微任务,再开始继续执行下一个宏任务 -
宏任务->执行结束->有可执行的微任务吗?(有则执行所有微任务)->开始新的宏任务
-
记住两点:
- 微任务在宏任务之前的执行,先执行 执行栈中的内容 执行后 清空微任务
- 每次取一个宏任务 就去清空微任务,之后再去取宏任务
宏任务和微任务都有哪些?
- 宏任务(MacroTask):
script
标签整体代码的执行、setTimeout
、setInterval
、I/O
、requestAnimationFrame
、UI Rendering
、setImmediate(Node.js 环境)
- 微任务(MicroTask):
Promise.then
、MutationObserver
、process.nextTick(Node.js环境)
、catch finally
加餐
console.log('script start');
setTimeout(function () {
console.log('setTimeout');
}, 0);
Promise.resolve()
.then(function () {
console.log('promise1');
})
.then(function () {
console.log('promise2');
});
console.log('script end');
//script start, script end, promise1, promise2, setTimeout
setTimeout(function () {
console.log('setTimeout1');
Promise.resolve().then(() => {
console.log('then1');
});
}, 0);
Promise.resolve().then(() => {
console.log('then2');
Promise.resolve().then(() => {
console.log('then3');
});
setTimeout(function () {
console.log('setTimeout2');
}, 0);
});
//then2 then3 setTimeout1 then1 setTimeout2
let a = () => {
setTimeout(() => {
console.log('任务队列函数1');
}, 0);
for (let i = 0; i < 1; i++) {
console.log('a的for循环');
}
console.log('a事件执行完');
};
let b = () => {
setTimeout(() => {
console.log('任务队列函数2');
}, 0);
for (let i = 0; i < 1; i++) {
console.log('b的for循环');
}
console.log('b事件执行完');
};
let c = () => {
setTimeout(() => {
console.log('任务队列函数3');
}, 0);
for (let i = 0; i < 1; i++) {
console.log('c的for循环');
}
console.log('c事件执行完');
};
a();
b();
c();
//a的for循环->a事件执行完->b的for循环->b事件执行完->c的for循环->c事件执行完->任务队列函数1->任务队列函数2->任务队列函数3
// 当a、b、c函数都执行完成之后,三个setTimeout才会依次执行