参考资料

EventLoop
事件队列分为 TaskQueue(宏任务队列) 和 MicrotaskQueue(微任务队列)两种。
事件队列分类
- TaskQueue:script标签引入的js代码,setTimeout,setInterval,IO,渲染...
- MicrotaskQueue:Promise、async/await...
事件循环执行
当执行栈中的任务清空,开始一次事件循环。
主线程会从 TaskQueue 取出一个Task执行。
然后检查MicrotaskQueue中是否有Task,如果有,清空当前MicrotaskQueue队列。
一次事件循环结束。
然后开始看执行栈是否为空,当为空时,开始下一次事件循环。不为空时,清空执行栈,然后开始下一次事件循环。
本次事件循环添加的MicrotaskQueue和TaskQueue,MicrotaskQueue在本次事件循环结束会被执行,TaskQueue 会在后续的事件循环中去执行
Demo
Demo1
<body>
测试事件循环机制
<div id="outer" class="outer">
<div id="inner" class="inner"></div>
</div>
<script src="./app1.js"></script>
<script src="./app2.js"></script>
</body>
// app1.js
console.log('app1.js 开始');
setTimeout(() => {
console.log('app1.js-setTimeout 2000ms 执行');
}, 20);
setTimeout(() => {
console.log('app1.js-setTimeout 1000ms 执行');
}, 10);
Promise.resolve().then(() => {
console.log('Promise.resolve()');
});
const promise1 = new Promise((resolve, reject) => {
console.log('app1.js-promise1 -init');
resolve('app1.js-promise1');
});
const promise2 = new Promise((resolve, reject) => {
console.log('app1.js-promise2 -init');
resolve('app1.js-promise2');
}).then(data => {
console.log('app1.js-promise2 第一次 then');
return data;
});
promise1
.then(data => {
console.log('app1.js-promise1 第一次 then');
return data;
})
.then(data => console.log(`app1.js-promise1 第二次 then--${data}`))
.then(data => console.log(`app1.js-promise1 第三次 then--${data}`))
.then(data => console.log(`app1.js-promise1 第四次 then--${data}`));
promise2.then(data => console.log(`app1.js-promise2 第二次 then--${data}`)).then(data => console.log(`app1.js-promise2 第三次 then--${data}`));
console.log('app1.js 结束');
// app2.js
console.log('app2.js 开始');
setTimeout(() => {
console.log('app2.js-setTimeout 2000ms 执行');
}, 20);
setTimeout(() => {
console.log('app2.js-setTimeout 1000ms 执行');
}, 10);
const promise3 = new Promise((resolve, reject) => {
console.log('app2.js-promise1 -init');
resolve('app2.js-promise1');
}).then(data => {
console.log('app2.js-promise1 第一次 then');
return data;
});
const promise4 = new Promise((resolve, reject) => {
console.log('app2.js-promise2 -init');
resolve('app2.js-promise2');
}).then(data => {
console.log('app2.js-promise2 第一次 then');
return data;
});
promise3
.then(data => console.log(`app2.js-promise1 第二次 then--${data}`))
.then(data => console.log(`app2.js-promise1 第三次 then--${data}`))
.then(data => console.log(`app2.js-promise1 第四次 then--${data}`));
promise4.then(data => console.log(`app2.js-promise2 第二次 then--${data}`)).then(data => console.log(`app2.js-promise2 第三次 then--${data}`));
console.log('app2.js 结束');
运行结果
// 主线程运行的执行栈代码
app1.js 开始
app1.js:12 app1.js-promise1 -init
app1.js:16 app1.js-promise2 -init
app1.js:31 app1.js 结束
// 执行栈清空,清空 MicrotaskQueue
app1.js:9 Promise.resolve()
app1.js:19 app1.js-promise2 第一次 then
app1.js:24 app1.js-promise1 第一次 then
app1.js:30 app1.js-promise2 第二次 then--app1.js-promise2
app1.js:27 app1.js-promise1 第二次 then--app1.js-promise1
app1.js:30 app1.js-promise2 第三次 then--undefined
app1.js:28 app1.js-promise1 第三次 then--undefined
app1.js:29 app1.js-promise1 第四次 then--undefined
// 执行栈没有可执行的,开始新一轮的事件循环,执行 MicrotaskQueue,
// MicrotaskQueue没有task,所以执行setTimeout
app1.js:6 app1.js-setTimeout 1000ms 执行
// 执行栈没有可执行的,开始新一轮的事件循环,执行 MicrotaskQueue,
// MicrotaskQueue没有task,所以执行setTimeout
app1.js:3 app1.js-setTimeout 2000ms 执行
// 执行栈没有可执行的,开始新一轮的事件循环,执行 MicrotaskQueue,
// MicrotaskQueue没有task,所以执行script 标签引入 app2.js 代码
app2.js:1 app2.js 开始
app2.js:9 app2.js-promise1 -init
app2.js:16 app2.js-promise2 -init
app2.js:27 app2.js 结束
app2.js:12 app2.js-promise1 第一次 then
app2.js:19 app2.js-promise2 第一次 then
app2.js:23 app2.js-promise1 第二次 then--app2.js-promise1
app2.js:26 app2.js-promise2 第二次 then--app2.js-promise2
app2.js:24 app2.js-promise1 第三次 then--undefined
app2.js:26 app2.js-promise2 第三次 then--undefined
app2.js:25 app2.js-promise1 第四次 then--undefined
app2.js:6 app2.js-setTimeout 1000ms 执行
app2.js:3 app2.js-setTimeout 2000ms 执行