广告
返回顶部
首页 > 资讯 > 精选 >nodejs中事件循环机制的示例分析
  • 221
分享到

nodejs中事件循环机制的示例分析

2023-06-14 22:06:11 221人浏览 安东尼
摘要

这篇文章主要介绍了nodejs中事件循环机制的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。前端开发离不开javascript,Javascript是一种web前端语

这篇文章主要介绍了nodejs中事件循环机制的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。

前端开发离不开javascript,Javascript是一种web前端语言,主要用于web开发中,由浏览器解析执行。而js的作用不仅仅局限于前端领域的开发,它同样可以用于服务端开发——nodejs。作为一名有理想抱负的前端,想要拓展视野,掌握一门服务器端开发语言,那么nodejs是非常好的一种选择。

因为你掌握了js开发方式就很容易上手node,并且npm包管理工具也大大提升了开发体验。nodejs以异步非阻塞I/O工作方式而闻名,其处理机制被称为事件循环。

了解node事件循环机制就能更好的了解node的事件处理方式以及异步事件的执行时机,本文主要讲解一下nodejs的事件循环机制,为后续学习node奠定基础。

一、node VS javascript

前面提到,Javascript是一种WEB前端语言,主要用于web开发中,由浏览器解析执行,而 node.js 是一个基于 Chrome V8 引擎的JavaScript 运行环境,因此nodejs不是一门语言,不是库,不是框架,而是一个js运行时环境,简单讲node可以解析和执行js代码。以前只有浏览器可以解析执行Js,现在node可以使js完全脱离浏览器来运行。

node.js和浏览器js存在很多区别,比如浏览器中的js包括了ecmascript、BOM、DOM,但是nodejs中的js没有BOM,DOM,只有emcscript。并且node这个js执行环境为js提供了一些服务器级别的操作api,例如:文件读写,网络服务构建,网络通信,Http服务器等,这些API大都被包装到核心模块里面了。另外node的事件循环机制和浏览器js的事件循环机制也不一样。

二、JavaScript事件循环

大家对浏览器中的js事件循环已经很清楚了,为了对比这里简单再提一下。

nodejs中事件循环机制的示例分析

(转引自Philip Roberts的演讲《Help, I'm stuck in an event-loop》)

js执行时同步和异步任务任务分别进入不同的执行环境,同步任务的进入主线程,即主执行栈,异步任务(ajax请求、settimeout、setinterval、poromise.resolve()等)进入任务队列。不同的异步任务会推入不同的任务队列,比如ajax请求、settimeout、setinterval等这些任务会被推入进宏任务队列(Macro Task),而Promise函数则会被推到微任务队列(Micro Task)。整体的事件循环过程如下:

  • 当同步代码执行完后,主执行栈变空,开始准备执行异步任务。

  • 主线程会检查微任务队列是否为空,如果不为空那么会遍历队列内的所有微任务将其执行完,清空微任务队列,然后再检查宏任务队列。如果微任务队列是空的,直接进入下一步。

  • 主线程遍历宏任务队列,并执行宏任务队列中的第一个宏任务,在执行的过程中如果遇到宏任务或者微任务,则继续将他们推入到对应的任务队列,每次执行完一次宏任务都要遍历执行一下微任务队列,将其清空

  • 执行渲染操作,更新视图

  • 开始下一次的事件循环,重复上述步骤直至两个任务队列清空

为了加深一下影响,举一个小小的,看看以下代码会输出什么:

    var le=Promise.resolve(2);    console.log(le)    console.log('3')    Promise.resolve().then(()=>{    console.log('Promise1')      setTimeout(()=>{        console.log('setTimeout2')    },0)    })    setTimeout(()=>{    console.log('setTimeout1')    Promise.resolve().then(()=>{        console.log('Promise2')        })    },0);

用以上的事件循环过程分析一下:

  • js主进程执行代码遇到Promise.resolve(2),会立即执行,将2变成一个promise对象,然后console.log(le)将le变量打印出来,打印----->Promise {<fulfilled>: 2};

  • console.log('3'),打印----->3

  • 接着往下执行遇到Promise.resolve().then,这是一个异步微任务函数,推到微任务栈

  • 下一个函数遇到setTimeout,推到宏任务队列,至此主进程空了

  • 检查微任务队列,发现Promise.resolve().then,所以打印----->promise1,又遇到一个定时器,推至宏任务队列的最后,微任务队列空了

  • 检查宏任务队列,取第一个宏任务执行,打印----->setTimeout1,又遇到 Promise.resolve().then,推至微任务队列

  • 再开始下一个宏任务之前,一定会清空微任务,因此打印setTimeout1后,便会检查微任务队列,于是--->promise2

  • 接下来又一轮事件循环,取宏任务队列当前的第一个任务执行,于是打印打印----->setTimeout2,至此宏任务和微任务队列均被清空,事件循环结束

因此输出结果是:Promise {<fulfilled>: 2},3,promise1,setTimeout1,promise2,setTimeout2。

浏览器里执行结果如下:

nodejs中事件循环机制的示例分析

三、node事件循环

node的事件循环共有六个阶段,在一次事件循环中这六个阶段按顺序会一直循环执行,直至事件处理完成。六个阶段的顺序图如下:

nodejs中事件循环机制的示例分析

六个阶段分别是:

  • timers 阶段:这个阶段执行timer(setTimeout、setInterval)的回调

  • I/O callbacks 阶段:执行一些系统操作的回调(比如网络通信的错误回调);

  • idle, prepare 阶段:仅node内部使用,可忽略

  • poll 阶段:获取新的I/O事件, 适当的条件下node将阻塞在这里

  • check 阶段:执行 setImmediate() 的回调

  • close callbacks 阶段:执行 Socket 的 close 事件回调,如果一个socket或handle被突然关掉(比如socket.destroy()),close事件将在这个阶段被触发

事件循环中,每当进入某一个阶段,都会从该阶段对应的回调队列中取出函数去执行。当队列为空或者执行的回调函数数量到达系统设定的阈值,该阶段就会终止,然后检查NextTick队列和微任务队列,将其清空,之后进入下一个阶段。

这里面比较关键的是poll阶段:

  • poll队列不为空的时候,事件循环会遍历队列并同步执行回调,直到队列清空或执行回调数达到系统上限。

  • poll队列为空的时候,就会有两种情况:

    • 如果代码中存在setImmediate()回调,那么事件循环直接结束poll阶段进入check阶段来执行check队列里的回调;

    • 如果不存在setImmediate()回调,会等待回调被加入到队列中并立即执行回调,这里同样会有个超时时间设置防止一直等待下去,如果规定时间内有定时器函数进入队列,则返回到timer阶段,执行定时器回调,否则在poll阶段等待回调进入队列。

同样的举个大大的,看看以下代码会输出什么:

console.log('start')setTimeout(() => {  console.log('timer1')  Promise.resolve().then(function() {    console.log('promise1')  })}, 0)setTimeout(() => {  console.log('timer2')  Promise.resolve().then(function() {    console.log('promise2')  })}, 0)Promise.resolve().then(function() {  console.log('promise3')})console.log('end')

利用node事件循环分析呗:

  • 先执行同步任务,打印start,end

  • 进入timer阶段前,清空NextTick和micro队列,所以打印promise3

  • 进入timer阶段,打印timer1,并发现有一个微任务,立即执行微任务,打印promise1

  • 仍然在timer阶段,执行下个宏任务,打印timer2,同样遇到微任务,立即执行,打印promise2

因此输出顺序是:start,end,promise3,timer1,promise1,timer2,promise2,如果能正确回答出来说明对node的循环机制有了大体的了解,实际node输出结果确实是这样:

nodejs中事件循环机制的示例分析

那如下代码会输出什么呢?

process.nextTick(function(){    console.log(7);});new Promise(function(resolve){    console.log(3);    resolve();    console.log(4);}).then(function(){    console.log(5);});process.nextTick(function(){    console.log(8);});

继续分析:

  • process.nextTick会将任务推进至nextTick队列,promise.then会把任务推至micro队列,上面提到过每次一个宏任务执行完,执行下一个宏任务之前需要清空nextTick队列和micro队列,同样的一个阶段执行完,进入下一个阶段之前也需要nextTick队列和micro队列,并且nextTick队列优先级高于micro队列

  • 先执行同步代码,打印3,4

  • 执行nextTick队列,打印7,8

  • 再执行micro队列,打印5

因此最终输出是:3,4,7,8,5,需要记住,process.nextTick 永远大于 promise.then的优先级

还有一个大家很容易混淆的点就是setTimout和setImmediate的执行时机,根据上面描述的node事件循环机制,setImmediate()应该在check阶段执行 与 而setTimeout在timer阶段执行,理论上setTimout比setImmediate先执行,看下面的代码:

setTimeout(() => console.log(1),0);setImmediate(() => console.log(2));

执行结果是什么?1,2 还是 2,1,其实都有可能,看实际node运行的结果:

nodejs中事件循环机制的示例分析

可以看到两次执行的结果不一样,为什么呢?原因在于即使setTimeout的第二个参数默认为0,但实际上,Node做不到0秒就执行其回调,最少也要4毫秒。那么进入事件循环后,如果没到4毫秒,那么timers阶段就会被跳过,从而进入check阶段执行setImmediate回调,此时输出结果是:2,1;

如果进入事件循环后,超过4毫秒(只是个大概,具体值并不确定),setTimeout的回调会出现在timer阶段的队列里,回调将被执行,之后再进入poll阶段和check阶段,此时输出结果是:1,2

那如果两者在I/O周期内调用,谁先执行呢?看一下代码:

const fs = require('fs')fs.readFile('./test.txt', 'utf8' , (err, data) => {  if (err) {    console.error(err)    return  }  setTimeout(() => {    console.log('timeout');  }, 0);  setImmediate(() => {    console.log('immediate');  });})

实际上,node中输出的结果总是immediate先输出,timeout后输出。因为I/O回调是在poll阶段执行,当回调执行完毕之后队列为空,发现存在setImmediate的回调就会进入check阶段,执行完毕后,再进入timer阶段。

感谢你能够认真阅读完这篇文章,希望小编分享的“nodejs中事件循环机制的示例分析”这篇文章对大家有帮助,同时也希望大家多多支持编程网,关注编程网精选频道,更多相关知识等着你来学习!

--结束END--

本文标题: nodejs中事件循环机制的示例分析

本文链接: https://www.lsjlt.com/news/275435.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • nodejs中事件循环机制的示例分析
    这篇文章主要介绍了nodejs中事件循环机制的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。前端开发离不开JavaScript,Javascript是一种web前端语...
    99+
    2023-06-14
  • nodejs中事件和事件循环的示例分析
    这篇文章主要介绍nodejs中事件和事件循环的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!nodejs中的事件循环虽然nodejs是单线程的,但是nodejs可以将操作委托给系统内核,系统内核在后台处理这些...
    99+
    2023-06-14
  • JS中事件循环机制的示例分析
    小编给大家分享一下JS中事件循环机制的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!1、JavaScript是单线程的JavaScript 是一种单线程的...
    99+
    2023-06-29
  • NodeJS事件循环实例分析
    这篇文章主要介绍“NodeJS事件循环实例分析”,在日常操作中,相信很多人在NodeJS事件循环实例分析问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”NodeJS事件循环实例分析”的疑惑有所帮助!接下来,请跟...
    99+
    2023-06-29
  • JS中浏览器事件循环机制的示例分析
    这篇文章将为大家详细讲解有关JS中浏览器事件循环机制的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。先来明白些概念性内容。进程、线程进程是系统分配的独立资源,是 ...
    99+
    2022-10-19
  • Node.js中事件循环的示例分析
    这篇文章主要介绍Node.js中事件循环的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!Node 自身的执行模型——事件循环,正是它使得回调函数十分普遍。在进程启动时,Nod...
    99+
    2022-10-19
  • JavaScript之事件循环的示例分析
    这篇文章主要介绍JavaScript之事件循环的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!js中的事件循环因为JavaScript是单线程的,同一事件只能执行一种方法,所以会将程序中的方法加入到执行栈中按...
    99+
    2023-06-20
  • Node.js事件循环机制实例代码分析
    这篇文章主要介绍“Node.js事件循环机制实例代码分析”,在日常操作中,相信很多人在Node.js事件循环机制实例代码分析问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Node.js事件循环机制实例代码分析...
    99+
    2023-07-04
  • 分析IOS RunLoop的事件循环机制
    在RunLoop启动之后会发送一个通知,来告知观察者 将要处理Timer/Source0事件这样一个通知的发送 处理Source0事件 如果有Source1要处理,这时会通过一个go...
    99+
    2022-05-18
    IOS RunLoop
  • javascript事件循环event loop的示例分析
    小编给大家分享一下javascript事件循环event loop的示例分析,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!具体如下:js是单线程的,但是event loop的出现,使得js...
    99+
    2022-10-19
  • JavaScript中事件机制的示例分析
    这篇文章主要介绍JavaScript中事件机制的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!事件是将JavaScript脚本与网页联系在一起的主要方式,是JavaScrip...
    99+
    2022-10-19
  • Ext.js4.2.1中事件机制的示例分析
    这篇文章主要为大家展示了“Ext.js4.2.1中事件机制的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Ext.js4.2.1中事件机制的示例分析”这篇文章吧。一: 简介Ext中的事件...
    99+
    2023-06-04
  • Flex事件机制的示例分析
    这篇文章主要为大家展示了“Flex事件机制的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Flex事件机制的示例分析”这篇文章吧。什么是Flex事件机制Flex事件可以看作是一种触发机制...
    99+
    2023-06-17
  • JavaScript事件循环实例分析
    这篇文章主要讲解了“JavaScript事件循环实例分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“JavaScript事件循环实例分析”吧!前言异步函数也是有执行顺序的。本质上来说,Ja...
    99+
    2023-07-02
  • Node.js中事件循环、定时器和process.nextTick()的示例分析
    这篇文章主要介绍Node.js中事件循环、定时器和process.nextTick()的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!什么是事件循环尽管JavaScript是...
    99+
    2022-10-19
  • Node中的事件循环、process.nextTick()实例分析
    这篇文章主要讲解了“Node中的事件循环、process.nextTick()实例分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Node中的事件循环、p...
    99+
    2022-10-19
  • Android事件分发机制示例分析
    Android事件类型 public boolean onTouchEvent(MotionEvent event) { switch (event.getActio...
    99+
    2022-11-13
  • Ajax中循环的示例分析
    小编给大家分享一下Ajax中循环的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!Ajax 简介Ajax 由 HTML、J...
    99+
    2022-10-19
  • js中事件传播机制的示例分析
    这篇文章主要介绍js中事件传播机制的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!事件的默认传播机制:  捕获阶段:从外向里依次查找元素  目标阶段:从当前事件源本身的操作 ...
    99+
    2022-10-19
  • vue中事件机制原理的示例分析
    这篇文章主要介绍了vue中事件机制原理的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。常见的事件机制demo都会包含在这段代码中:&...
    99+
    2022-10-19
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作