首页前端开发JavaScript一文带你了解Node.js中的eventloop

一文带你了解Node.js中的eventloop

时间2024-01-31 04:03:03发布访客分类JavaScript浏览564
导读:收集整理的这篇文章主要介绍了一文带你了解Node.js中的eventloop,觉得挺不错的,现在分享给大家,也给大家做个参考。主线程从"任务队列"中读取事件,这个过程是循环不断的,所以整个的这种运行机制又称为Event Loop(事件循环)...
收集整理的这篇文章主要介绍了一文带你了解Node.js中的eventloop,觉得挺不错的,现在分享给大家,也给大家做个参考。主线程从"任务队列"中读取事件,这个过程是循环不断的,所以整个的这种运行机制又称为Event Loop(事件循环)。下面本篇文章就来带大家掌握Node.js中的EventLoop,希望对大家有所帮助!

其实在前面的文章我也讲述过浏览器中的eventloop。然而在NodeJs中的eventloop与浏览器的是有区别的。对于写nodejs的人来说掌握eventloop是一项很重要的技能。因为这意味着你不仅是会写js,而对NodeJs也是有研究的。

为什么要有eventloop?

我们知道NodeJs的本质是把浏览器的v8搬到了操作系统中运行,因此也把浏览器的事件循环拿过来了。可是为什么会出现eventloop这样的设计呢?

从历史原因上来看,js在设计时只是一门很简单的为了在页面上操作一下dom的语言(相信大家都听过js只用了10天就设计出来的故事)。出于这个目标,我们当然希望js的运行尽可能的简单,轻量,有多轻呢?轻到js的渲染引擎是在一个线程中运行的。

那么问题来了如果是在一个线程上运行js,当代码是线性的时候,当然是没有问题的。但在页面上,我们需要用户的交互,而这些交互是不知道为什么时候发生的。那js要怎么处理?如果眼前有正在运行的代码,一个用户交互进来之后,程序该怎么反应?如果先处理用户的交互,那原来的程序就会被暂停(也就是阻塞)。为了避免这种阻塞,js采用了一个办法,就是用一个消息队列,来存放这种用户交互。等所有的程序跑完之后,再去消息队列中拿交互事件,然后执行。这样就解决了阻塞的问题了。

浏览器的eventloop

我们都知道浏览器在浏览页面的时候,用户交互是随时可能发生的,为了可以即时响应用户。js是不会关闭的,他会不停的循环。大致如下:

向消息队列拿任务-->
    执行任务-->
    执行完毕-->
     向消息队列拿任务-->
     ....

当然我们在之前的事件循环文章中讲过,为了给不同的异步任务分类,在事件循环中其实是有宏任务和微任务的区分的。他们的执行大致为

向消息队列拿微任务-->
    执行微任务-->
    微任务执行完毕-->
     向消息队列拿宏任务-->
    执行宏任务-->
    宏任务执行完毕-->
    向消息队列拿微任务-->
    ...

NodeJs的eventloop

node的事件循环其实大致思路跟在浏览器上的是相似的,但nodeJs对不同的宏任务又作出了不同时期的区分。下面是官方的流程图:

可以看到nodeJs中每次事件循环被分成了具体的6个时期,每个时期会用指定的宏任务。然后在每个时期的宏任务执行之前,会优先执行完微任务队列。

总览

timers执行由setTimeout()setInterval() 触发的回调
PEnding callbacks执行延迟到下一个循环迭代的I / O回调
idle, PRepare只在内部使用,开发者可以不关注
poll检索新的I / O事件; 执行I / O相关的回调(会执行几乎所有的回调,除了 close callbacks 以及 timers 调度的回调和 setImmediate() 调度的回调,在恰当的时机将会阻塞在此阶段)
check执行setImmediate()
close callbacks比如socket.on('close', ...)

其实通过上述表格,我们已经很清晰知道整个事件循环机制的执行顺序了。但可能大家还会有一些疑问。下面来详细讲一下。

pending callbacks

这个阶段其实是处理由于操作系统出错,导致一些本应在上次事件循环中执行的回调。例如一些TCP错误。因此这部分,开发者不能主动操作,是NodeJs的一些容错机制。

check

同样的,setImmediate是nodejs特有的api,他可以立即创建一个异步宏任务。不仅如此,nodejs在事件循环中还专门设了一个check时期,在这个时期会专门执行setImmediate的回调。甚至你可以在这个时期中如果不停的产生setImmediate回调,eventloop会优先处理。

close callbacks

这个时期处理关闭事件,如socket.on('close', ...) 等这样可以确保在一些通讯结束前,所有任务都完成了。

微任务在eventloop中

我们先来回顾浏览器与nodejs的差异:

宏任务:

任务浏览器Node
I/O
setTimeout
setInterval
setImmediate
requestAnimationFrame

微任务:

任务浏览器Node
process.nextTick
MutationObserver
Promise.then catch finally

可以看到process.nextTick是nodejs特有的微任务,不仅如此,process.nextTick()的优先级高于所有的微任务,每一次清空微任务列表的时候,都是先执行 process.nextTick()

执行差异

不仅是任务类型上有差异,在执行上2个环境其实也有差异。在浏览器上执行任务的时候,每执行一个宏任务之前,需要先确保微任务队列执行完了。而在nodejs上是每个时期之前,先确保微任务队列执行完。也就是说在假如在timer时期,会先把所有setTimeout,setInterval的宏任务执行完。在执行完微任务,再进入下个时期。

注意:以上执行规则是在nodejs的v11版本之前的规则。在11版本之后nodejs的执行输出是跟浏览器一样的。

setImmediate() vs setTimeout()

setImmediate() 和 setTimeout()的执行先后顺序是不一定的,就是说如果你不停地执行以下代码,每次得到的结果可能是不一样的。

setTimeout(() =>
 {
      console.LOG('timeout');
}
    , 0);
    setImmediate(() =>
 {
      console.log('immediate');
}
    );
    

其中的原因是程序对时间的处理是有误差的。在setTimeout方法中设置的时间,不一定是准确的。同时在回调触发时,也无法确认事件循环处在哪个时期,可能是timer,也可能是check。所有会有不同的结果。

总结

eventloop是js运行机制里的重点内容,对于NodeJs来说,eventloop的操作空间则更大。因为它被细分为不同的时期,从而让我们可能把逻辑进一步细化。同时利用nextTick的最高优先级,可以写出在浏览器无法实现的代码。因此对于深入NodeJs的开发者来说,eventloop往往是他们考察新人对NodeJs理解的第一步。

更多node相关知识,请访问:nodejs 教程!!

以上就是一文带你了解Node.js中的eventloop的详细内容,更多请关注其它相关文章!

声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!

上一篇: 探索下浏览器和 Node.js 为什么会...下一篇:一文带你搞懂JavaScript中的原型...猜你在找的JavaScript相关文章 html font标签如何设置字体大小?html font标签属性用法介绍2022-05-16vue3+TypeScript+vue-router的使用方法2022-04-16vue3获取当前路由地址2022-04-16如何利用React实现图片识别App2022-04-16JavaScript展开运算符和剩余运算符的区别详解2022-04-16微信小程序中使用vant框架的具体步骤2022-04-16Vue elementUI表单嵌套表格并对每行进行校验详解2022-04-16如何利用Typescript封装本地存储2022-04-16微信小程序中wxs文件的一些妙用分享2022-04-16JavaScript的Set数据结构详解2022-04-16 其他相关热搜词更多phpjavapython程序员loadpost-format-gallery

若转载请注明出处: 一文带你了解Node.js中的eventloop
本文地址: https://pptw.com/jishu/593455.html
探索下浏览器和 Node.js 为什么会这样设计 EventLoop! 用C++实现数据的管理功能

游客 回复需填写必要信息