浏览器和nodejs事件循环区别

浏览器和 nodejs 事件循环的区别

题目

浏览器和 nodejs 事件循环的区别

单线程和异步

JS 是单线程的,浏览器中 JS 和 DOM 渲染线程互斥。

单线程,代码就必须“串行”执行,无法并行,同一时间只能干一件事。

在 Java 等多线程语言中,发起请求、设置定时任务可以通过新开一个线程来处理,这就是并行。

而 JS 是单线程,这种场景就只能使用“异步”。

console.log('start')
setTimeout(() => {
    console.log('hello')
})
console.log('end')

宏任务和微任务

浏览器端异步的 API 有很多

  • 宏任务:setTimeout 网络请求
  • 微任务:promise

两者表面的区别:

第一,微任务比宏任务更快执行

console.log('start')
setTimeout(() => {
    console.log('timeout')
})
Promise.resolve().then(() => {
    console.log('promise.then')
})
console.log('end')

第二,微任务在 DOM 渲染前执行,而宏任务在 DOM 显示后(即真正显示到页面上,肉眼可见)执行

const p = document.createElement('p')
p.innerHTML = 'new paragraph'
document.body.appendChild(p)
console.log('length----', list.length)

console.log('start')
setTimeout(() => {
    const list = document.getElementsByTagName('p')
    console.log('timeout----', list.length)
    alert('阻塞')
})
Promise.resolve().then(() => {
    const list = document.getElementsByTagName('p')
    console.log('promise.then----', list.length)
    alert('阻塞')
})
console.log('end')

浏览器的事件循环

主要的流程

  • 执行 JS 同步代码(执行异步 API 时,异步先放在一个队列中,先不执行)
  • DOM 渲染
  • 执行队列中的异步函数(执行异步 API 时,异步先放在一个队列中,先不执行)—— 异步中可能还嵌套异步
  • DOM 渲染
  • 执行队列中的异步函数(执行异步 API 时,异步先放在一个队列中,先不执行)
  • DOM 渲染

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Oaeex5kX-1689084306280)(./img/event-loop.png)]

考虑宏任务和微任务

  • 执行 JS 同步代码(异步函数,分别放在 macroTaskQueue 和 microTaskQueue )
  • DOM 结构渲染(此时还没有在页面显示,但可以获取 DOM 内容了)
  • 执行 microTaskQueue 函数(异步中还可能嵌套异步…)
  • 显示 DOM 到页面
  • 执行 macroTaskQueue 函数(异步中还可能嵌套异步…)

nodejs 异步

nodejs 也是用了 V8 引擎和 ES 语法,所以也有同步、异步,异步也分宏任务、微任务。

  • setTimeout setInterval —— 宏任务
  • promise 和 async/await —— 微任务
  • process.nextTick —— 微任务,但优先级最高
  • setImmediate —— 宏任务
  • I/O 文件、网络 —— 宏任务
  • Socket 连接:连接 mysql —— 宏任务
console.log('start')
setImmediate(() => {
    console.log('immediate1')
})
setTimeout(() => {
    console.log('timeout1')
})
Promise.resolve().then(() => {
    console.log('promise then')
})
process.nextTick(() => {
    console.log('nextTick')
})
console.log('end')

nodejs 事件循环

浏览器的各种宏任务,都是按照代码的顺序执行的,没有其他优先级。

nodejs 的宏任务是分了如下类型,nodejs 事件循环中宏任务需要按照这个顺序来执行。

  • timers(计时器) - 执行 setTimeout 以及 setInterval 的回调
  • I/O callbacks - 处理网络、流、TCP 的错误回调
  • idle, prepare — 闲置阶段 - node 内部使用
  • poll(轮循) - 执行 poll 中的 I/O 队列,检查定时器是否到时间
  • check(检查) - 存放 setImmediate 回调
  • close callbacks - 关闭回调,例如 socket.on('close')

nodejs 事件循环的过程

  • 执行同步代码
  • 执行 process.nextTick 和微任务(前者优先级更高)
  • 按照顺序执行 6 个类型的宏任务

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iqxBsu6g-1689084306281)(./img/event-loop-nodejs.png)]

答案

  • 事件循环的大概模式相同
  • 宏任务有优先级区分
  • process.nextTick 在微任务的优先级更高

但是,process.nextTick 在最新版 nodejs 中不被推荐使用,推荐使用 setImmediate
原因在于 process.nextTick 是在当前帧介绍后立即执行,会阻断IO并且有最大数量限制(递归时会有问题)
setImmediate 不会阻断 IO ,更像是 setTimeout(fun, 0)

注意

基于 nodejs 最新版。nodejs 旧版会有所不同,特别注意。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值