js和node事件循环区别

本文详细解释了JavaScript的单线程事件循环机制,区分了同步任务与异步任务,特别强调了宏任务和微任务的区别,以及async/await如何转化为微任务。同时讨论了Node.js和浏览器事件循环的差异。
摘要由CSDN通过智能技术生成

javaScript事件循环机制

一、是什么?

JavaScript是一门单线程语言,同一时间只能做一件事,但并不意味着单线程就是阻塞,而实现单线程非阻塞的方式就是事件循环。

JavaScript中,所有的任务都可以分为:

  • 同步任务:立即执行的任务,同步任务一般会直接进入到主线程中执行
  • 异步任务:异步执行的任务,例如ajax请求,或者setTimeout函数

从上面可以看出,同步任务进入主线程,异步任务进入任务队列,主线程内的任务执行完毕为空,会去读取任务队列对应的任务,推入主线程执行。上述过程不断重复就是事件循环机制。

二、宏任务与微任务

异步任务又分为宏任务与微任务

微任务

  • script (可以理解为外层同步代码)
  • setTimeout/setInterval
  • setImmediate、I/O(Node.js)

微任务

  • Promise.then
  • process.nextTick(NodeJS)

执行宏任务时,遇到微任务就放入微任务任务队列中,当宏任务执行完成后,会查看微任务的事件队列,然后将微任务依次执行完,再进行循环执行下一个宏任务。

node:

  • Timers:用于存储定时器额回调函数(setInterval,setTimeout)
  • Pending callbacks:执行与操作系统相关的回调函数,比如启动服务器端应用时监听端口操作的回调函数就在这里调用。
  • 闲置阶段(idle, prepare):仅系统内部使用
  • 轮询阶段(poll):检索新的 I/O 事件;执行与 I/O 相关的回调(几乎所有情况下,除了关闭的回调函数,那些由计时器和 setImmediate() 调度的之外),其余情况 node 将在适当的时候在此阻塞
  • 检查阶段(check):setImmediate() 回调函数在这里执行
  • 关闭事件回调阶段(close callback):一些关闭的回调函数,例如关闭数据库连接的回调

区别:

Node.js 中的事件循环和浏览器中的事件循环有一些关键的区别,尽管它们都是用于处理异步操作的机制。以下是它们之间的一些主要区别:

1.基于环境:


Node.js:事件循环是 Node.js 运行时的一部分,它负责管理异步操作,例如文件 I/O、网络请求等。
浏览器:事件循环是浏览器引擎的一部分,用于处理诸如 DOM 事件、Ajax 请求等浏览器特定的异步操作。


2.事件循环实现:


Node.js:Node.js 使用 libuv 库来实现事件循环。libuv 是一个跨平台的异步 I/O 库,它提供了事件循环以及线程池等功能,用于管理异步操作。
浏览器:浏览器中的事件循环由浏览器引擎实现,通常是由 Blink(Chrome 和 Opera 使用的引擎)、Gecko(Firefox 使用的引擎)或 WebKit(Safari 使用的引擎)等实现。


3.事件队列:


Node.js:Node.js 有多个事件队列,其中包括 timers 队列(setTimeout 和 setInterval 回调)、I/O 队列(处理文件 I/O、网络 I/O 等)、微任务队列(process.nextTick 和 Promise)以及 setImmediate 队列(在每个事件循环迭代结束时执行)。
浏览器:浏览器也有多个事件队列,包括宏任务队列(例如 DOM 事件、Ajax 请求等)、微任务队列(Promise 和 MutationObserver 回调)、requestAnimationFrame 队列等。


4.主线程阻塞:


Node.js:Node.js 是单线程的,当执行 CPU 密集型操作或阻塞操作时,会导致事件循环被阻塞,从而影响其他异步操作的执行。
浏览器:浏览器是多线程的,JavaScript 代码运行在主线程上,但浏览器还有其他线程,如渲染线程、网络线程等。主线程阻塞可能会导致页面渲染被延迟。

====================

为什么 async/await 是微任务

async/await 在 JavaScript 中是用于处理异步操作的语法糖,它基于 Promise 实现,并且在语义上更加清晰和简洁。当使用 async/await 时,await 关键字会等待一个 Promise 解决(fulfilled)或拒绝(rejected),然后继续执行下一条语句。因此,await 关键字后面的代码会被封装成一个微任务,以便在当前执行栈清空之后立即执行。
下面是为什么 async/await 是微任务的一些原因:

1.与 Promise 密切相关:async/await 是基于 Promise 实现的,await 关键字等待的是一个 Promise 对象的状态。由于 Promise 的 then 方法注册的回调函数属于微任务,因此 await 后面的代码也会作为微任务来执行。
2.顺序执行:async/await 语法让异步代码看起来像同步代码一样顺序执行,因此,await 后面的代码应该在当前任务执行结束后立即执行,以保持程序的顺序执行语义。
3.处理异步结果:await 后面的代码通常是在等待异步操作的结果,并且需要在 Promise 解决后立即执行,以便处理异步操作的结果。
4.避免阻塞:与传统的 Promise 链相比,async/await 更容易编写和理解,并且可以避免回调地狱的问题。将 await 后面的代码作为微任务执行可以确保不会阻塞主线程,从而保持应用的响应性。

总之,async/await 是基于 Promise 的一种语法糖,它将异步代码变得更加清晰和易于理解。将 await 后面的代码作为微任务执行是为了保持顺序执行语义,并确保异步操作的结果能够及时地被处理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值