这是我参与更文挑战的第5天,活动详情查看: 更文挑战。
什么是事件循环?
javascript在浏览器和v8引擎里运行,javaScript是单线程非阻塞的语言。
那么是如何做到非阻塞执行的呢?靠的就是事件循环。
事件循环执行逻辑
在事件循环中,每进行一次循环操作称为 tick,每一次 tick 的任务处理模型是比较复杂的,但关键步骤如下:
- 执行一个宏任务(栈中没有就从事件队列中获取)
- 执行过程中如果遇到微任务,就将它添加到微任务的任务队列中
- 宏任务执行完毕后,立即执行当前微任务队列中的所有微任务(依次执行)
- 当前宏任务执行完毕,开始检查渲染,然后GUI线程接管渲染
- 渲染完毕后,JS线程继续接管,开始下一个宏任务(从事件队列中获取)
简单总结一下执行的顺序:
执行宏任务,然后执行该宏任务产生的微任务,若微任务在执行过程中产生了新的微任务,则继续执行微任务,微任务执行完毕后,再回到宏任务中进行下一轮循环。
优先级:微任务>宏任务
任务分类
宏任务
- 一段新程序或子程序被直接执行时
- 触发了一个事件,将其回调函数添加到任务队列时。
- 执行到一个由 setTimeout() 或 setInterval() 创建的 timeout 或 interval,以致相应的回调函数被添加到任务队列时。
- postMessage
- requestAnimationFrame
微任务
- promises :Promise.then、Promise.catch、Promise.finally等相关api。
- MutationObserver(html5 新特性)
- queueMicrotask(自定义微任务)
node和浏览器里的事件循环的区别
node11及以后版本和浏览器里的执行顺序一致。
事件循环面试题目
题目一
async function async1() {
console.log('async1 start');
await async2();
console.log('async1 end');
}
async function async2() {
console.log('async2');
}
console.log('script start');
setTimeout(function() {
console.log('setTimeout');
}, 0)
async1();
new Promise(function(resolve) {
console.log('promise1');
resolve();
}).then(function() {
console.log('promise2');
});
console.log('script end');
复制代码
执行结果如下:
script start
async1 start
async2
promise1
script end
async1 end
promise2
setTimeout
注意async函数里的await后的代码都是异步执行的,及promise.then中的执行顺序。
题目二
console.log('start');
setTimeout(() => {
console.log('children2');
Promise.resolve().then(() => {
console.log('children3');
})
}, 0);
new Promise(function(resolve, reject) {
console.log('children4');
setTimeout(function() {
console.log('children5');
resolve('children6')
}, 0)
}).then((res) => {
console.log('children7');
setTimeout(() => {
console.log(res);
}, 0)
})
复制代码
执行结果:
start
children4
children2
children3
children5
children7
children6
题目三
const p = function() {
return new Promise((resolve, reject) => {
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(1)
}, 0)
resolve(2)
})
p1.then((res) => {
console.log(res);
})
console.log(3);
resolve(4);
})
}
p().then((res) => {
console.log(res);
})
console.log('end');
复制代码
执行结果:
3
end
2
4
参考资料
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END