浏览器事件循环和NodeJs事件环
一、浏览器事件循环(eventLoop)
- 由于js是单线程,所以代码执行时,是由上至下执行,这样会阻塞代码进程。于是浏览器环境中(v8引擎)出现了任务队列,即在将代码分为同步代码和异步代码。
- 异步代码分为宏任务和微任务。
- 微任务执行优先级比宏任务执行优先级高
- 每次宏任务执行完都会将微任务队列的执行
执行顺序
- 代码执行流程图
执行流程图
二、NodeJs事件环
- 与浏览器事件循环相似,但有所不同
- 异步任务的任务数不同
- 微任务执行顺序不是队列顺序
- 微任务process.nextTick()优先级高于promise 执行!!
- 宏任务之间切换不会立马查微任务,而是先执行完宏任务才去执行微任务!!(貌似弃用)
- 官网描述
验证序号3,例子
setTimeout(() => {
console.log("s1");
Promise.resolve().then(() => {
console.log("p1");
});
process.nextTick(()=>{
console.log("t1");
})
});
Promise.resolve().then(() => {
console.log("p2");
});
console.log("sync start")
setTimeout(() => {
console.log("s2");
Promise.resolve().then(() => {
console.log("p3");
});
process.nextTick(()=>{
console.log("t2");
})
});
console.log("sync end");
输出
sync start
sync end
p2
s1
t1 //优先于 同作用域下 promise
p1
s2
t2 //优先于 同作用域下 promise
p3
2.1 关于NodeJs事件环存在的“问题”
setTimeout(() => {
console.log("s1");
});
setImmediate(() => {
console.log('d1');
});
上述代码连续多次执行,打印结果如下。
出现的原因是由于setTimeout的毫秒数默认为0的情况下,在执行环境存在差异,会导致有时setImmediate先入队列,有时setTimeout先入。
因此,有的时候会先是timer阶段开始,即setTimeout,有的时候会check阶段,既setImmediate
2.2 与上一个问题相似的“问题”
同样的代码放入io操作却不同
const fs = require('fs')
// 随便读取一个文件,I/O文件操作。处理轮询的poll阶段
fs.readFile('./httpServer.js',()=>{
setTimeout(() => {
console.log("s1");
});
setImmediate(() => {
console.log('d1');
});
})
打印结果如下,无论连续执行次数,结果都是先执行setImmediate()
出现原因,NodeJs宏任务执行机制是由上至下的,所以文件操作在poll阶段,接下来会先执行check阶段的任务,即setImmediate,再到setTimeout.
因此,即使setTimeout毫秒延迟数存在差异,也无关影响
参考链接:NodeJs官方文档
在线作图工具:processOn