什么是js事件循环?
javascript是单线程的,执行代码的时候会逐行的执行,碰到异步代码(发起ajax请求,执行setTimeout)会挂起放入到消息队列里,继续执行后边的代码,执行完毕以后才会执行消息队列的代码(面试之前的理解)
测试代码
<script>
console.log('start')
setTimeout(() => {
console.log('setTimeout start')
}, 0)
for (var i = 0; i < 10; i++) {
console.log('循环执行')
}
const p1 = new Promise((resolve, reject) => {
console.log('构造函数执行')
resolve(1)
}).then(res => {
console.log('then1', res)
return res
}).catch(err => {
console.log('err', err);
})
Promise.resolve(2).then(_ => console.log('then2', 2))
console.log('end')
</script>
打印结果:
代码改造为中途添加点击任务
为了效果明显,我把定时器时间改为4s后运行,for循环改为3000次,当我们重新执行一次代码,并且连续点击按钮
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button onclick="onclick1()">按钮</button>
<script>
console.log('start')
function onclick1() {
console.log('按钮点击了');
}
setTimeout(() => {
console.log('setTimeout start1')
}, 1000)
setTimeout(() => {
console.log('setTimeout start2')
}, 4000)
for (var i = 0; i < 3000; i++) {
console.log('循环执行')
}
const p1 = new Promise((resolve, reject) => {
console.log('构造函数执行')
resolve(1)
}).then(res => {
console.log('then1', res)
return res
}).catch(err => {
console.log('err', err);
})
Promise.resolve(2).then(_ => console.log('then2', 2))
console.log('end')
</script>
</body>
</html>
打印结果如下:
总结
- javascript是单线程的,执行代码的时候碰到异步代码会挂起,继续执行后边的代码
- setTimeout,setInterval的回调函数会加入到宏任务的消息队列
- Promise的then()方法里边的函数会加入到微任务的消息队列
- 在一次事件循环里,当主线程空闲时(执行栈清空了),会优先执行微任务消息队列的任务,直到清空微任务队列
- 微任务的队列清空以后,主线程会执行宏任务队列里边满足当次循环的任务,不一定清空队列,例如设置4s的定时器就不在这次的事件循环执行,我们点击13次按钮后才打印的定时器,说明在第13次事件循环执行的第二个定时器的宏任务