详解node.js 事件循环


Posted in Javascript onJuly 22, 2020

Node.js 是单进程单线程应用程序,但是因为 V8 引擎提供的异步执行回调接口,通过这些接口可以处理大量的并发,所以性能非常高。

Node.js 几乎每一个 API 都是支持回调函数的。

Node.js 基本上所有的事件机制都是用设计模式中观察者模式实现。

Node.js 单线程类似进入一个while(true)的事件循环,直到没有事件观察者退出,每个异步事件都生成一个事件观察者,如果有事件发生就调用该回调函数.

事件驱动程序

Node.js 使用事件驱动模型,当web server接收到请求,就把它关闭然后进行处理,然后去服务下一个web请求。

当这个请求完成,它被放回处理队列,当到达队列开头,这个结果被返回给用户。

这个模型非常高效可扩展性非常强,因为 webserver 一直接受请求而不等待任何读写操作。(这也称之为非阻塞式IO或者事件驱动IO)

在事件驱动模型中,会生成一个主循环来监听事件,当检测到事件时触发回调函数。

详解node.js 事件循环

整个事件驱动的流程就是这么实现的,非常简洁。有点类似于观察者模式,事件相当于一个主题(Subject),而所有注册到这个事件上的处理函数相当于观察者(Observer)。

Node.js 有多个内置的事件,我们可以通过引入 events 模块,并通过实例化 EventEmitter 类来绑定和监听事件,如下实例:

// 引入 events 模块
var events = require('events');
// 创建 eventEmitter 对象
var eventEmitter = new events.EventEmitter();

以下程序绑定事件处理程序:

// 绑定事件及事件的处理程序
eventEmitter.on('eventName', eventHandler);

我们可以通过程序触发事件:

// 触发事件
eventEmitter.emit('eventName');

实例

创建 main.js 文件,代码如下所示:

// 引入 events 模块
var events = require('events');
// 创建 eventEmitter 对象
var eventEmitter = new events.EventEmitter();
 
// 创建事件处理程序
var connectHandler = function connected() {
  console.log('连接成功。');
 
  // 触发 data_received 事件 
  eventEmitter.emit('data_received');
}
 
// 绑定 connection 事件处理程序
eventEmitter.on('connection', connectHandler);
 
// 使用匿名函数绑定 data_received 事件
eventEmitter.on('data_received', function(){
  console.log('数据接收成功。');
});
 
// 触发 connection 事件 
eventEmitter.emit('connection');
 
console.log("程序执行完毕。");

接下来让我们执行以上代码:

$ node main.js
连接成功。
数据接收成功。
程序执行完毕。

Node 应用程序是如何工作的?
在 Node 应用程序中,执行异步操作的函数将回调函数作为最后一个参数, 回调函数接收错误对象作为第一个参数。

接下来让我们来重新看下前面的实例,创建一个 input.txt ,文件内容如下:

三水点靠木 3water

创建 main.js 文件,代码如下:

var fs = require("fs");

fs.readFile('input.txt', function (err, data) {
  if (err){
   console.log(err.stack);
   return;
  }
  console.log(data.toString());
});
console.log("程序执行完毕");

以上程序中 fs.readFile() 是异步函数用于读取文件。 如果在读取文件过程中发生错误,错误 err 对象就会输出错误信息。

如果没发生错误,readFile 跳过 err 对象的输出,文件内容就通过回调函数输出。

执行以上代码,执行结果如下:

程序执行完毕
三水点靠木 3water

接下来我们删除 input.txt 文件,执行结果如下所示:

程序执行完毕
Error: ENOENT, open 'input.txt'

因为文件 input.txt 不存在,所以输出了错误信息。

以上就是详解node.js 事件循环的详细内容,更多关于node.js 事件循环的资料请关注三水点靠木其它相关文章!

Javascript 相关文章推荐
网页图片延时加载的js代码
Apr 22 Javascript
js下用eval生成JSON对象
Sep 17 Javascript
把文本中的URL地址转换为可点击链接的JavaScript、PHP自定义函数
Jul 29 Javascript
JavaScript中的toUTCString()方法使用详解
Jun 12 Javascript
全系IE支持Bootstrap的解决方法
Oct 19 Javascript
初步使用bootstrap快速创建页面
Mar 03 Javascript
javascript html5 canvas实现可拖动省份的中国地图
Mar 11 Javascript
Easyui的组合框的取值与赋值
Oct 28 Javascript
Vue自定义指令详解
Jul 28 Javascript
基于Vue2x的图片预览插件的示例代码
May 14 Javascript
vue实现滑动超出指定距离回顶部功能
Jul 31 Javascript
JavaScript实现雪花飘落效果
Dec 27 Javascript
jQuery+ThinkPHP实现图片上传
Jul 23 #jQuery
详解vue中v-on事件监听指令的基本用法
Jul 22 #Javascript
使用vue实现通过变量动态拼接url
Jul 22 #Javascript
浅谈JavaScript窗体Window.ShowModalDialog使用
Jul 22 #Javascript
解决vue里a标签值解析变量,跳转页面,前面加默认域名端口的问题
Jul 22 #Javascript
vue props 一次传多个值实例
Jul 22 #Javascript
微信小程序动态评分展示/五角星展示/半颗星展示/自定义长度展示功能的实现
Jul 22 #Javascript
You might like
239军机修复记
2021/03/02 无线电
for循环连续求和、九九乘法表代码
2012/02/20 PHP
Server.HTMLEncode让代码在页面里显示为源代码
2013/12/08 PHP
CodeIgniter启用缓存和清除缓存的方法
2014/06/12 PHP
php常用表单验证类用法实例
2015/06/18 PHP
在Mac OS上自行编译安装Apache服务器和PHP解释器
2015/12/24 PHP
简单谈谈PHP面向对象之标识对象
2017/06/27 PHP
Javascript下IE与Firefox下的差异兼容写法总结
2010/06/18 Javascript
使用Jquery来实现可以输入值的下拉选单 雏型
2011/12/06 Javascript
Javascript图像处理—虚拟边缘介绍及使用方法
2012/12/27 Javascript
浅谈关于JavaScript API设计的一些建议和准则
2015/06/24 Javascript
Bootstrap CSS组件之导航(nav)
2016/12/17 Javascript
微信小程序 用户数据解密详细介绍
2017/01/09 Javascript
你可能不知道的JSON.stringify()详解
2017/08/17 Javascript
Bootstrap table使用方法记录
2017/08/23 Javascript
js 提取某()特殊字符串长度的实例
2017/12/06 Javascript
axios的拦截请求与响应方法
2018/08/11 Javascript
详解webpack打包时排除其中一个css、js文件或单独打包一个css、js文件(两种方法)
2018/10/26 Javascript
nodejs提示:cross-device link not permitted, rename错误的解决方法
2019/06/10 NodeJs
[02:38]DOTA2 夜魇暗潮2020活动介绍官方视频
2020/11/04 DOTA
python中global与nonlocal比较
2014/11/21 Python
python logging日志模块的详解
2017/10/29 Python
Django 解决阿里云部署同步数据库报错的问题
2020/05/14 Python
Matplotlib自定义坐标轴刻度的实现示例
2020/06/18 Python
在pycharm中文件取消用 pytest模式打开的操作
2020/09/01 Python
python模块内置属性概念及实例
2021/02/18 Python
启动一个线程是用run()还是start()
2016/12/25 面试题
Servlet如何得到服务器的信息
2015/12/22 面试题
制药工程专业应届生求职信
2013/09/24 职场文书
机械制造与自动化应届生求职信
2013/11/16 职场文书
电气自动化专业职业规划范文
2014/02/16 职场文书
小班评语大全
2014/05/04 职场文书
大专生找工作自荐书
2014/06/10 职场文书
机关作风建设自查报告
2014/10/22 职场文书
JS不要再到处使用绝对等于运算符了
2021/04/30 Javascript
HttpClient实现文件上传功能
2022/08/14 Java/Android