Eventloop 说一下
setTimeout(function () {
console.log(4);
}, 0);
new Promise(function (resolve) {
console.log(1);
resolve();
console.log(2);
}).then(function () {
console.log(5);
});
console.log(3);
//打印顺序
1
2
3
5
4
肤浅理解:『一会儿』和『尽快』异步任务
宏任务:一会儿就做的异步任务 微任务:尽快做的异步任务
参考文章:https://juejin.cn/post/6924160592353689613 > https://www.cnblogs.com/zhangnan35/p/11268655.html
详细理解:Eventloop 是个啥?
Event Loop 即事件循环,是指浏览器或 Node 的一种解决 javaScript 单线程运行时不会阻塞的一种执行机制,也就是我们经常使用异步的原理。
执行栈
- 一个专门用来存放执行代码的栈内存结构,它就像一个容器,也叫做执行的主线程。
- 如果遇到函数,会根据回调关系把回调层级深的函数先推入到执行栈底部执行,其他语句依次推入,当全部执行完了后,会从上到下依次弹出执行代码(也就是“先进后出”),供下一次使用;
宏任务和微任务(针对浏览器)
JavaScript 中有两种异步任务:宏任务和微任务
宏任务:(宿主环境提供的任务)
- script(整体代码)
- setTimeout
- setInterval
- setImmediate
- I/O
- UI rendering
微任务:(JS 自带的任务)
- Promise
- Object.observe
- MutationObserver
timers: 计时器,执行 setTimeout 和 setInterval 的回调
pending callbacks: 执行延迟到下一个循环迭代的 I/O 回调
idle, prepare: 队列的移动,仅系统内部使用
poll 轮询: 检索新的 I/O 事件;执行与 I/O 相关的回调。事实上除了其他几个阶段处理的事情,其他几乎所有的异步都在这个阶段处理。
check: 执行 setImmediate 回调,setImmediate 在这里执行
close callbacks: 执行 close 事件的 callback,一些关闭的回调函数,如:socket.on('close', ...)
执行规则是什么?
同步代码->执行全部微任务->单个宏任务->全部微任务->...
每个 API 对应哪个任务队列?(浏览器与 Nodejs 混合)
setTimeout
setImmediate(浏览器没有)
process.nextTick(浏览器没有)
MutationObserver(Node 没有)
promise.then
await
答案
宏任务队列:
- setTimeout
- setImmediate(浏览器没有)
微任务队列:
- process.nextTick(浏览器没有)
- promise.then
- MutationObserver(Node 没有)
- await
实例一
这种题目尽量说思路,因为你不可能通过眼睛看出结果(必须画图)
async function async1() {
console.log(1);
await async2();
console.log(2);
}
async function async2() {
console.log(3)
}
async1();
new Promise(function (resolve) {
console.log(4);
resolve();
}).then(function () {
console.log(5);
});
//打印顺序
1
3
4
2
5
注意:这一题的答案不唯一,在 Node.js 和 Chrome 的结果不一样,甚至在 Chrome 上也是时而这个答案,时而那个答案。所以还是说思路最重要。
答案:
先判断是否是浏览器事件循环或者 Nodejs 事件循环:查看是否有 setImmediate 和 process.nextTick,只有 Nodejs 才有。
确定是浏览器的 Event Loop
JavaScript 中有两种异步任务:宏任务和微任务
遇到宏任务,加入宏任务任务队列中;
遇到微任务,加入在当前宏任务的微任务度列中。每个宏任务会创建自己的微任务队列。
JS 同步代码执行完之后,宏任务即将结束之前,将该宏任务对应的微任务队列的任务全部取出依次执行。
若执行过程中又遇到微任务则加入当前微任务队列队尾。
微任务队列清空后本轮 eventloop 结束。
从任务队列取出一个宏任务,将宏任务中的代码取出,初始化全局上下文开始执行。
实例二
setTimeout(function f1(){
console.log(1)
Promise.resolve().then(function f2(){
setTimeout(function f3(){
console.log(3)
})
console.log(2)
})
})
setTimeout(function f4(){
console.log(4)
Promise.resolve().then(function f5() {
setTimeout(function f6() {
console.log(5)
})
console.log(6)
})
})
//打印顺序
1
2
4
6
3
5