1、Event Loop?

Event Loop 其实也是在面试中经常会出现的一个题,前端程序员回答不上来是正常的,因为 Event Loop 是 C++ 实现的,实现原理和 JavaScript 没什么关系,我个人在之前的面试中遇到这个题的时候,也是看一些 C++ 程序员对 Event Loop 的分析,如果你想对 Event Loop 有一个深入的了解,那这里推荐你一篇 Event Loop 的官方文档,这有中文版:Event Loop。

在了解 Event Loop 之前我们可能需要一点计算机操作系统的知识,比如:当开发人员在电脑键盘上敲击了 a 键,那操作系统是如何知道的呢?大概是这样的,当 a 键盘被按下时,a 键的信息会通过键盘内的电路传递给操作系统,然后操作系统再通知浏览器,浏览器在得到 a 键的信息之后,就会将 a 显示到响应的位置。一句话,浏览器会接收到操作系统传递给它的事件。

那什么是 Event 事件?比如 setTimeout(fun1, delay) 在 delay 到时后需要执行的回调函数 fun1 就是事件,或者 fs.readFile("/1.txt', fun2) 文件读取后执行的 fun2 也是事件,再或者 http 网络请求相关的 server.on('close', fun3) ,在服务器关闭时执行的 fun3 也是事件。

那什么是 Loop 循环?Loop 就是循环的意思,比如我们学习编程过程中的 for、while 循环,它们是一个道理的。但是由于 Event 事件是分优先级的,所以在处理的时候也是要分先后顺序的,Node.js 就是按照顺序来轮询每种事件的。

Event Loop?回到上述所说的 Event 事件的问题,假如上述的场景,操作系统同时触发了三种事件,那 Node 会怎么办?答案是这几种事件有一个优先级分类,然后根据优先级排序执行,这就是 Event Loop 对事件处理顺序的管理。那这个顺序是怎样的呢?

2、Event Loop 顺序?

JavaScript 是单线程的,有了 event loop 的加持,Node.js 才可以非阻塞地执行 I/O 操作,把这些操作尽量转移给操作系统来执行。

浏览器使用了 V8 自带的 Event Loop 事件循环机制,它只有宏任务和微任务之间的循环,而 Node.js 是基于 libuv 自己做了一个 Event Loop,它的事件循环就相对比较复杂。首先看一下浏览器的事件循环:

  • JS 的任务队列分 macro-task(宏任务)与 micro-task(微任务),在最新标准中,它们被分别称为task与jobs。
  • macro-task 包括:script(整体代码), setTimeout, setInterval, setImmediate, I/O, UI rendering。
  • micro-task 包括: process.nextTick, Promise., Object.observe(已废弃), MutationObserver(html5新特性)

Node.js 的事件循环分为六个阶段,如下图所示:其中每个方框都是 event loop 中的一个阶段。每个阶段都有一个 先入先出队列,这个队列存有要执行的回调函数(注:存的是函数地址)。不过每个阶段都有其特有的使命,一般来说,当 event loop 达到某个阶段时,会在这个阶段进行一些特殊的操作,然后执行这个阶段的队列里的所有回调。

   ┌───────────────────────────────────┐
┌─>│        timers 检查计时器的callback │
│  └──────────┬────────────────────────┘
│  ┌──────────┴────────────────────────┐
│  │     I/O callbacks                 │
│  └──────────┬────────────────────────┘
│  ┌──────────┴────────────────────────┐
│  │     idle, prepare                 │
│  └──────────┬────────────────────────┘      ┌───────────────┐
│  ┌──────────┴────────────────────────┐      │   incoming:   │
│  │         poll 轮询,检查系统事件     │<─────┤  connections, │
│  └──────────┬────────────────────────┘      │   data, etc.  │
│  ┌──────────┴────────────────────────┐      └───────────────┘
│  │      check 检查 setImmediate 回调  │
│  └──────────┬────────────────────────┘
│  ┌──────────┴────────────────────────┐
└──┤    close callbacks                │└───────────────────────────────────┘
  • timer 阶段:用于监测是否含有计时器的回调事件,如果有的话就执行,没有的话就进入下一阶段。
  • I/O callbacks:监测是否含有其他的回调,比如 TCP 报错,如果一个 TCP socket 开始连接时出现了 ECONNREFUSED 错误,一些 *nix 系统就会(向 Node.js)通知这个错误。这个通知就会被放入 I/O callbacks 队列。
  • idle,prepare:空闲阶段,一般用来清理一下内存相关,忽略不计。
  • poll:轮询,检查系统事件。这个阶段用来处理大部分事件,比如读文件,处理 http 请求等。
  • check:检查 setImmediate 回调,如果有的话就执行,没有的话就进入下一阶段。
  • close callbacks:执行关闭事件的回调函数,如 socket.on('close', fun) 里的 fun。

一个 Node.js 程序结束时,Node.js 会检查 event loop 是否在等待异步 I/O 操作结束,是否在等待计时器触发,如果没有,就会关掉 event loop。需要注意的是:大部分时间,Node.js 都停在 poll 轮询阶段,大部分事件都在 poll 阶段被处理,如文件、网络请求。

3、setImmediate() vs setTimeout()

setImmediate 和 setTimeout 很相似,但是其回调函数的调用时机却不一样。setImmediate() 的作用是在当前 poll 阶段结束后调用一个函数。setTimeout() 的作用是在一段时间后调用一个函数。这两者的回调的执行顺序取决于 setTimeout 和 setImmediate 被调用时的环境。

如果 setTimeout 和 setImmediate 都是在主模块(main module)中被调用的,那么回调的执行顺序取决于当前进程的性能,这个性能受其他应用程序进程的影响。举例来说,如果在主模块中运行下面的脚本,那么两个回调的执行顺序是无法判断的。但是,如果把上面代码放到 I/O 操作的回调里,setImmediate 的回调就总是优先于 setTimeout 的回调。

/* timeout_vs_immediate.js*/                      /* timeout_vs_immediate.js*/
setTimeout(() => {                                const fs = require('fs');console.log('timeout');                         fs.readFile(__filename, () => {
}, 0);                                                setTimeout(() => {console.log('timeout');
setImmediate(() => {                                  }, 0);console.log('immediate');                           setImmediate(() => {
});                                                       console.log('immediate');});
/*运行结果可能不同: */                             });
$ node timeout_vs_immediate.js                    //运行结果皆为:
timeout                                           $ node timeout_vs_immediate.js
immediate                                         immediatetimeout
$ node timeout_vs_immediate.js
immediate
timeout

setImmediate 的主要优势就是,如果在 I/O 操作的回调里,setImmediate 的回调总是比 setTimeout 的回调先执行。

Event Loop 事件循环简介相关推荐

  1. 为什么JS是单线程?JS中的Event Loop(事件循环)?JS如何实现异步?setimeout?

    https://segmentfault.com/a/1190000012806637 https://www.jianshu.com/p/93d756db8c81 首先,请牢记2点: (1) JS是 ...

  2. node.js中对Event Loop事件循环的理解

    javascript是单线程的,所以任务的执行都需要排队,任务分为两种,一种是同步任务,一种是异步任务. 同步任务是进入主线程上排队执行的任务,上一个任务执行完了,下一个任务才会执行. 异步任务是不进 ...

  3. Event Loop事件循环机制

    转载自:阮一峰博客<JavaScript 运行机制详解:再谈Event Loop> 一.为什么JavaScript是单线程? JavaScript语言的一大特点就是单线程,也就是说,同一个 ...

  4. node mysql 事件循环_NodeJs 的 Event loop 事件循环机制详解

    什么是事件轮询 事件循环是 Node.js 处理非阻塞 I/O 操作的机制--尽管 JavaScript 是单线程处理的--当有可能的时候,它们会把操作转移到系统内核中去. 下面的图表显示了事件循环的 ...

  5. JavaScript event loop事件循环 macrotask与microtask

    macrotask  姑且称为宏任务,在很多上下文也被简称为task.例如: setTimeout, setInterval, setImmediate, I/O, UI rendering. mic ...

  6. Even Loop(事件循环机制)

    1.什么是事件循环机制 Event Loop即事件循环,是解决javaScript单线程运行阻塞的一种机制. 2.为什么使用Even Loop 原因:JavaScript 是单线程的.单线程就意味着, ...

  7. Eevnt Loop (事件循环)

    javascript是一门单线程的非阻塞的脚本语言.单线程意味着javascript在执行代码的任何时候,都只有一个主线程来处理所有的任务.非阻塞:是当代码需要进行一项异步任务(无法立刻返回结果,需要 ...

  8. php循环套循环_PHP中的事件循环简介

    php循环套循环 PHP developers are always waiting for something. Sometimes we're waiting for requests to re ...

  9. event loop 事件轮询机制

    1,event loop(事件轮询/事件循环) 首先我们要知道 由于js是单线程的脚本,异步事件要基于回调来实现的 而event loop 就是异步回调的实现原理 1,js的执行顺序 从前到后,一行一 ...

最新文章

  1. 22岁复旦大学生拿下深度学习挑战赛冠军:明明可以靠脸吃饭,却偏偏要靠才华
  2. GPT-3数学不及格,愁坏伯克利团队,于是他们出了12500道数学作业
  3. 究竟什么样的简历才能拿到面试?
  4. 安卓总线传输协议常用关键词
  5. 不肯嫁的几种男人(转)
  6. GCC编译器的安装教程(Windows环境)
  7. 重心法求中心matlab,两个中转站选址问题(重心法,metlab,spss)程序.ppt
  8. 面向对象------转自林海峰老师
  9. 江阴学计算机,江阴学习计算机平面设计
  10. 移动开发之三种近场通信
  11. 如何查询自己的个人征信报告
  12. 怎样成为“吃鸡”沙漠霸主?掌握资源点是关键
  13. 新算法可干扰脸部识别系统
  14. 自学Python第二十二天- Django框架(一)创建项目、APP、快速上手、请求和响应流程、模板、数据库操作
  15. Accumulation point
  16. 如何去除短视频中的硬字幕
  17. 2年5个月13天,从外包到拿下阿里offer,没想到我也能有今天
  18. vue 接入萤石云,实现监控、多窗口监控、转向、放大缩小等
  19. 关于电容器的泄漏电流
  20. PHP是核心思路,模拟oicq的实现思路和核心程序(一) _php实例

热门文章

  1. 全能flash滚动条,响应任意鼠标事件
  2. IDC许可证是什么,如何办理IDC增值电信业务经营许可证年报
  3. iOS 交易支付密码(多种样式选择)~ 封装demo
  4. 全国青少年编程等级考试scratch二级真题2019年3月(含题库答题软件账号)
  5. 入门电机系列之4步进电机
  6. Node.js联机游戏——gobang五子棋(客户端+服务端+websocket的双人游戏)
  7. GPS时间转化成标准时间格式
  8. 【2019年05月07日】A股最便宜的股票
  9. 利用多线程实现的下载器,完爆迅雷!
  10. oracle11g_xe下手工创建odbc数据源