# 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('111');
setTimeout(function () {
console.log('setTimeout');
}, 0);
new Promise(function (rev) {
console.log('Promise');
rev();
})
.then(function () {
console.log('promise1');
setTimeout(() => {
console.log('setTimeout-then');
}, 0);
})
.then(function () {
console.log('promise2');
})
.then(function () {
console.log('promise3');
});
(async () => {
console.log('async');
await console.log('await');
console.log('after-await');
setTimeout(() => {
console.log('setTimeout2');
(async () => {
console.log('async-then');
await console.log('await-then');
console.log('after-await-then');
setTimeout(() => console.log('setTimeout-await-then'), 0);
})();
}, 0);
})();
(async () => {
console.log('async1');
await console.log('await1');
console.log('after-await1');
setTimeout(() => console.log('setTimeout3'), 0);
})();
console.log('script end');
// 111
// Promise
// async
// await
// async1
// await1
// script end
// promise1
// after-await
// after-await1
// promise2
// promise3
// setTimeout
// setTimeout-then
// setTimeout2
// async-then
// await-then
// after-await-then
// setTimeout3
// setTimeout-await-then
# 加餐
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才会依次执行