网易首页 > 网易号 > 正文 申请入驻

如何理解Node.js的事件循环

0
分享至

作者:陈峻 来源:51CTO

【51CTO.com快译】由于JavaScript是单线程的,那么在浏览器中,为了在等待动作完成时不会阻塞主线程的异步代码处理,JavaScript使用事件循环在调用堆栈、Web API和回调队列之间,持续协调代码的执行。不过,由Node.js自行实现的Node.js事件循环,虽然与之有着许多相同的模式,但是由于Node.js不与DOM交互,且可以处理各种输入和输出(I/O),因此它在工作方式上却有所不同。

在本文中,我们将先了解Node.js事件循环背后的理论,再探究几个使用setTimeout、setImmediate和process.nextTick的示例。最后,我们将部分工作代码部署到Heroku(这一种快速部署应用的简便方法,请参阅--https://www.heroku.com/)中,以查看其运行情况。

Node.js的事件循环

总的说来,Node.js事件循环可以协调计时器、回调、以及I/O事件等操作与执行。这便是Node.js在单线程的情况下,处理异步行为的方式。如下事件循环图,很好地展示了其执行的顺序。

如您所见,Node.js事件循环共有六个主要阶段,它们分别是:

  • 计时器(Timers):那些由setTimeout和setInterval安排的回调,会在此阶段被执行。
  • 待处理的回调(Pending callbacks):那些被推迟到下一个循环迭代的I/O回调,会在此阶段被执行。
  • 空闲,准备(Idle, prepare):此阶段仅由Node.js内部所使用。
  • 轮询(Poll):此阶段用于检索新的I/O事件,并执行I/O回调(不过那些由计时器和setImmediate安排的回调,以及下面将提到的关闭回调除外,毕竟它们会在其他不同的阶段被处理)。
  • 检查(Check):由setImmediate安排的回调会在该阶段被执行。
  • 关闭回调(Close callbacks):此阶段主要执行诸如销毁套接字连接等回调。

您可能会好奇,为何process.nextTick并未在上述任何阶段被提到?其实,这是因为:作为一种特殊的方法,就技术而言,它并非Node.js事件循环的一部分。相反,无论process.nextTick方法在何时被调用,它都会将自己的回调放入队列之中,然后“无论事件循环当前处于哪个阶段,都会在完成当前操作后,处理排队中的各种回调”(源自:Node.js事件循环文档)。

事件循环的场景示例

也许您觉得上文针对Node.js事件循环的每个阶段的解释,过于抽象了。那么,我在Heroku上创建了一个包含了各种可运行代码段示例的演示应用,请参见--https://nodejs-event-loop-demo.herokuapp.com/。在该应用中,单击任何示例按钮,都会向服务器端发送一个API请求。而Node.js会在后端执行所选示例的代码片段,然后通过API将相应的响应返回给前端。您可以从GitHub的链接处,查看到完整的代码。

让我们通过如下示例,来更好地理解Node.js事件循环的调用顺序。

示例1

让我们从如下简单的示例开始(如下图所示):

在此,我们有三个功能函数。由于它们是同步的,因此代码会从上至下顺次执行。也就是说,如果三个函数的调用顺序为:first、second、third,它们的代码也会以相同的顺序去执行:first、second、third。

示例2

接下来,我们会在第二个示例中引入setTimeout的概念(如下图所示):

在此,我们先调用first函数,然后在延迟0毫秒后计划调用带有setTimeout的second函数,最后调用third函数。那么,这些函数的执行顺序就变成了:first、third、second。您一定会好奇:为什么second函数会被最后执行呢?

下面让我们来理解两个重要的原则。首先,使用带有延迟值的setTimeout方法,并不意味着应用将在指定毫秒数后,立即执行回调函数。实际上,该值表示的是:执行回调之前,需要经过的最短时间。其次,使用setTimeout来为回调设定的后期执行时间,会在事件循环的每一次迭代期间中始终执行该规则。因此,在事件循环的第一次迭代中,first函数被执行,second函数被“安排”(scheduled),third函数再被执行。然而,在事件循环的第二次迭代期间中,0毫秒的最小延迟已被满足,因此second函数便会在第二次迭代的“计时器”阶段被执行。

示例3

然后,我们会在第三个示例中引入setImmediate的概念(如下图所示):

在该示例中,我们执行first函数,使用setTimeout来为second函数延迟0毫秒,然后使用setImmediate来“安排”third函数。那么,在代码执行的过程中,就会出现一个问题:到底是哪种类型的安排优先?setTimeout还是setImmediate?

鉴于前面已经讨论过setTimeout的工作机制,我们来简单介绍一下setImmediate方法。该方法在事件循环的下一次迭代的“检查”阶段,会去执行其回调函数。因此,如果setImmediate在事件循环的第一次迭代期间被调用,那么它的回调方法会被“安排”上,并在事件循环的第二次迭代期间,执行该回调方法。

正如你在输出中所看到的那样,在我们的示例中,由于被setImmediate安排的回调先于被setTimeout安排的回调执行,因此该示例函数的执行顺序为:first、third、second。

当然,由setImmediate和setTimeout安排的执行到底谁先谁后,实际上取决于被调用方法的上下文。当从Node.js脚本中的主模块,直接调用这两种方法时,其时间取决于进程的性能,因此在每次运行脚本时,回调都可以按照不同的顺序被执行。不过,在I/O周期内调用这些方法时,setImmediate回调总是发生在setTimeout回调之前。在我们上述示例中,由于这些方法是作为响应API端点的某个部分被调用的,因此setImmediate回调会始终在setTimeout回调之前被执行。

示例4

为了实现快速的健全性检查,我们使用setImmediate和setTimeout来构建另一个示例(如下图所示)。

在此示例中,我们使用setImmediate来安排first函数,接着直接执行second函数,然后使用setTimeout的0毫秒延迟来安排third函数。您恐怕已经猜到了,上述函数的执行顺序为:second、first、third。而在事件循环的第二次迭代中,second函数被setImmediate安排在该I/O周期内被执行,然后third函数在延迟0毫秒时间后也被执行了。

示例5

下面,我们将process.nextTick方法引入最后一个示例(如下图所示)。

在该示例中,我们使用setImmediate来安排first函数,并使用process.nextTick来安排second函数,再使用带有0毫秒延迟的setTimeout来安排third函数,最后执行fourth函数。那么,在代码运行后,整体的调用顺序为:fourth、second、first、third。

有了前面的基础,我们很容易理解fourth函数为何被首先执行了。毕竟它是被直接调用的,而无需通过任何其他方法来进行安排。process.nextTick方法安排了second函数在第二个被执行,first函数紧接其后。最后被执行的是third函数,其原因在于,在同一个I/O周期内,由setImmediate安排的回调会先于setTimeout安排的回调去执行。

那么,为什么由process.nextTick安排的second函数会先于由setImmediate安排的first函数被执行呢?请不要被这两种方法的名称所误导,并非setImmediate就代表着回调一定会被立即执行,而process.nextTick就一定要等到事件循环的下一轮再执行回调。在此,我们并不展开讨论,如果您有兴趣的话,请参见https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/#process-nexttick-vs-setimmediate。您只需注意的是:process.nextTick是在安排的同一阶段中,立即执行回调的;而setImmediate的回调则是在事件循环的下一次迭代、或计时期间中被执行的。

小结

通过上述示例,您应该对Node.js的事件循环,以及诸如setTimeout、setImmediate和process.nextTick等方法有所了解了。当然,您不必深究Node.js的内部结构,以及处理命令的相关操作。我们完全可以将Node.js视为一个黑匣子,轻松地用好Node.js事件循环的各项调用顺序即可。为了进一步了解上面提到的各种示例,您可以通过链接—https://nodejs-event-loop-demo.herokuapp.com/来查看其demo应用,或者通过链接—https://github.com/thawkin3/nodejs-event-loop-demo查看它们在GitHub上的代码。您甚至可以通过参考--https://heroku.com/deploy?template=https://github.com/thawkin3/nodejs-event-loop-demo,将代码部署到Heroku处。

原文标题:Understanding the Node.js Event Loop,作者: Tyler Hawkins

【51CTO译稿,合作站点转载请注明原文译者和出处为51CTO.com】

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
特鲁姆普对香港世界大奖赛非常失望!墨菲:很多人不知道这项赛事

特鲁姆普对香港世界大奖赛非常失望!墨菲:很多人不知道这项赛事

世界体坛观察家
2026-02-24 09:11:40
存款100万后,请立刻放下这三个习惯。

存款100万后,请立刻放下这三个习惯。

流苏晚晴
2026-02-24 18:54:06
突发!武汉知名宝马4s店被申请破产!

突发!武汉知名宝马4s店被申请破产!

三农老历
2026-02-24 22:06:15
暴涨!有相机价格翻10倍,根本抢不到,杭州姑娘傻眼,马上翻出家里老古董

暴涨!有相机价格翻10倍,根本抢不到,杭州姑娘傻眼,马上翻出家里老古董

环球网资讯
2026-02-22 16:48:12
电影《夜王》冲破4500万!黄子华评英国不留情面,即食面赢晒全场

电影《夜王》冲破4500万!黄子华评英国不留情面,即食面赢晒全场

情感大头说说
2026-02-24 01:10:59
美媒评26年自由市场10大控卫!火箭队范乔丹屈居第5 哈登意外落选

美媒评26年自由市场10大控卫!火箭队范乔丹屈居第5 哈登意外落选

锅子篮球
2026-02-24 22:10:05
10万志愿军被包围,彭老总无从下手,毛主席:放弃救援,以攻代守

10万志愿军被包围,彭老总无从下手,毛主席:放弃救援,以攻代守

谈古论今历史有道
2026-02-23 12:00:03
确认访华后,特朗普突然变脸对中国加税!却迎来两大噩耗浇灭野心

确认访华后,特朗普突然变脸对中国加税!却迎来两大噩耗浇灭野心

阿讯说天下
2026-02-24 16:15:29
姚笛再次复出!她变美了不少,脸上的哀愁消失了,整个人变化很大

姚笛再次复出!她变美了不少,脸上的哀愁消失了,整个人变化很大

背包旅行
2026-02-23 15:02:37
76%日本人支持?高市早苗点名中国,话音刚落,中方连出2重击!

76%日本人支持?高市早苗点名中国,话音刚落,中方连出2重击!

纾瑶
2026-02-24 17:05:07
被称为“中国最大忽悠”的贾跃亭,似乎要翻身了。

被称为“中国最大忽悠”的贾跃亭,似乎要翻身了。

流苏晚晴
2026-02-19 16:19:47
iPhone 18 Pro灵动岛缩小35%,将首发搭载基于台积电2nm工艺制造的A20 Pro芯片

iPhone 18 Pro灵动岛缩小35%,将首发搭载基于台积电2nm工艺制造的A20 Pro芯片

中国能源网
2026-02-24 12:01:06
当因杀死毒贩,而让半个国家燃起战火后,终于理解了墨西哥的绝望

当因杀死毒贩,而让半个国家燃起战火后,终于理解了墨西哥的绝望

阅微札记
2026-02-24 17:06:05
县城消费「限时繁荣」了十天

县城消费「限时繁荣」了十天

镜相工作室
2026-02-24 09:06:36
哪一瞬间你觉得众生皆苦?网友:怎么在外国很少听到这种事情

哪一瞬间你觉得众生皆苦?网友:怎么在外国很少听到这种事情

带你感受人间冷暖
2026-02-22 08:03:33
女孩当小姐,一晚要提供4到5次上门服务,2015年被亲人点到不赴约

女孩当小姐,一晚要提供4到5次上门服务,2015年被亲人点到不赴约

汉史趣闻
2025-11-08 09:27:32
谷爱凌14岁就说自己是中国人:我不是老外 会不会说中文有打区别

谷爱凌14岁就说自己是中国人:我不是老外 会不会说中文有打区别

念洲
2026-02-24 16:34:24
美伊26日谈判在即 是否对伊朗动武:白宫先内讧了

美伊26日谈判在即 是否对伊朗动武:白宫先内讧了

环球网资讯
2026-02-24 07:25:18
他们干掉了最大的毒枭,没想到整个国家却烧起来了...

他们干掉了最大的毒枭,没想到整个国家却烧起来了...

英国那些事儿
2026-02-23 23:28:04
《卫报》:普京曾认为90%的乌克兰人会支持入侵

《卫报》:普京曾认为90%的乌克兰人会支持入侵

时尚的弄潮
2026-02-24 11:47:43
2026-02-24 23:44:49
Nodejs开发
Nodejs开发
分享只有程序员懂的干货
648文章数 823关注度
往期回顾 全部

科技要闻

宇树科技发布四足机器人Unitree As2

头条要闻

男子搂住继女强吻动作亲密 当地妇联介入

头条要闻

男子搂住继女强吻动作亲密 当地妇联介入

体育要闻

苏翊鸣总结米兰征程:我仍是那个热爱单板滑雪的少年

娱乐要闻

汪小菲官宣三胎出生:承诺会照顾好3个孩子

财经要闻

县城消费「限时繁荣」了十天

汽车要闻

入门即满配 威兰达AIR版上市 13.78万元起

态度原创

本地
教育
家居
艺术
军事航空

本地新闻

春花齐放2026:《骏马奔腾迎新岁》

教育要闻

因为孩子们的一个疑问,这堂课上了8个月

家居要闻

本真栖居 爱暖伴流年

艺术要闻

2025年第八届全国青年美展 | 油画作品选刊

军事要闻

美军参联会主席警告:对伊朗动武可能带来重大风险

无障碍浏览 进入关怀版