# Event Loop
# 什么是 event loop?
- 虽然 js 是单线程的语言,但是在运行上存在
同步任务
和异步任务
,具体表现为执行顺序不相同,event loop 机制规定了 js 的执行顺序,使得 js 单线程运行时不会阻塞 - Javascript 有一个主线程
main thread
和调用栈(执行栈)call-stack
和任务队列task queue
,所有的任务都会被放到调用栈等待主线程执行 - 同步任务会在调用栈中按照入栈顺序待主线程执行,异步任务的回调会在满足条件后被放入任务队列,主线程清空调用栈后会再去执行队列中的异步任务的回调
- 异步任务又分为
宏任务
与微任务
,而主线程从任务队列中取出一个宏任务并执行,执行完毕后会清空队列中的微任务,再开始继续执行下一个宏任务
操作0=>operation: 宏任务
操作1=>operation: 执行结束
条件1=>condition: 有可执行的微任务吗?
操作2=>operation: 执行所有微任务
操作0->操作1->条件1(yes)->操作2->操作0
条件1(no)->操作1
- 记住两点:
- 微任务在宏任务之前的执行,先执行 执行栈中的内容 执行后 清空微任务
- 每次取一个宏任务 就去清空微任务,之后再去取宏任务
# 宏任务和微任务都有哪些?
- 宏任务(MacroTask):
script
标签整体代码的执行、setTimeout
、setInterval
、I/O
、requestAnimationFrame
、UI Rendering
、setImmediate(Node.js 环境)
- 微任务(MicroTask):
Promise.then
、MutationObserver
、process.nextTick(Node.js环境)
、catch finally
,V8的垃圾回收过程
# 加餐
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才会依次执行