Node.js 是单进程单线程应用程序,但是因为 V8 引擎提供的异步执行回调接口,通过这些接口可以处理大量的并发,所以性能非常高。它几乎每一个 API 都是支持回调函数的,基本上所有的事件机制都是用设计模式中观察者模式实现,它的单线程类似进入一个while(true)的事件循环,直到没有事件观察者退出,每个异步事件都生成一个事件观察者,如果有事件发生就调用该回调函数。

Node.js 使用事件驱动模型,当web server接收到请求,就把它关闭然后进行处理,然后去服务下一个web请求。当这个请求完成,它被放回处理队列,当到达队列开头,这个结果被返回给用户。这个模型非常高效可扩展性非常强,因为webserver一直接受请求而不等待任何读写操作(这也被称之为非阻塞式IO或者事件驱动IO)。在事件驱动模型中,会生成一个主循环来监听事件,当检测到事件时触发回调函数。来看下流程图:

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

它有多个内置的事件,我们可以通过引入 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 ,文件内容如下:

luyaran is my love

我们来创建 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 对象的输出,文件内容就通过回调函数输出,来看下运行结果:

程序执行完毕
luyaran is my love

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

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

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

在这里,我们要注意,Node.js 是单进程单线程应用程序,但是通过事件和回调支持并发,所以性能非常高。

再来看下什么是单进程单线程?

例举:cpu比作我们每个人,到饭点吃饭了。可以点很多菜(cpu中的进程):宫保鸡丁,鱼香肉丝,酸辣土豆丝。每样菜具体包含了哪些内容(cpu每个进程中的线程):宫保鸡丁(详情:黄瓜、胡萝卜、鸡肉、花生米)。而详情构成了宫保鸡丁这道菜,吃了以后不饿。就可以干活了,cpu中的进程里的线程也是同理。当线程完成自己的内容将结果返回给进程,进程返回给cpu的时候。cpu就能处理日常需求。

  • 单进程单线程:一盘炒苦瓜,里面只有苦瓜。
  • 单进程多线程:一盘宫保鸡丁,里面有黄瓜、胡萝卜、鸡肉、花生米

我们再来看事件。

事件就是需要 eventEmitter.on 去绑定一个事件 通过 eventEmitter.emit 去触发这个事件其次说的是 事件的 接收发生 是分开的 就像 一个外卖店你可以不停的接受很多订单, 接受以后开始告诉厨师去做外卖, 做好的外卖对应的外送给每个用户,如果单线程的话那只能是接收一个订单, 做好以后在接收下一个外卖订单,明显效率非常低。事件可以不停的接受不停的发生也是为了提高效率。

eventEmitter.emit 是触发事件(事件请求),eventEmitter.on是绑定处理事件的处理器(事件处理),事件的请求和处理是分开的,所以是异步。

如果把下面两个例子写在一起执行:

//例子1
var fs = require("fs");
fs.readFile('text.txt',
function(err, data) {if (err) return console.error(err);console.log(data.toString());console.log("end");console.log("***********************");
});
//例子2
var events = require("events");
var eventEmitter = new events.EventEmitter();
var connectHandler = function connected() {console.log("connnect successfully !");eventEmitter.emit("after_connect");
}
eventEmitter.on("connected", connectHandler);
eventEmitter.on('after_connect',
function() {console.log("after connect");
});
eventEmitter.emit("connected");
console.log("event emitter end");

我们会发现,例子 2 先输出,例子 1 后输出,可以验证是异步的,因为例子 1 需要进行 IO 耗时较长,但是例子 2 是直接输出信息,耗时较短,在两者几乎同时执行的情况下,例子 2 优先执行完。

好啦,本次记录就到这里了。

如果感觉不错的话,请多多点赞支持哦。。。

node总结之事件循环了解下相关推荐

  1. Node.js event loop 和 JS 浏览器环境下的事件循环的区别

    Node.js  event loop 和 JS 浏览器环境下的事件循环的区别: 1.线程与进程: JS 是单线程执行的,指的是一个进程里只有一个主线程,那到底什么是线程?什么是进程? 进程是 CPU ...

  2. Node - 异步IO和事件循环

    前言 学习Node就绕不开异步IO, 异步IO又与事件循环息息相关, 而关于这一块一直没有仔细去了解整理过, 刚好最近在做项目的时候, 有了一些思考就记录了下来, 希望能尽量将这一块的知识整理清楚, ...

  3. JavaScript执行机制-node事件循环

    node环境下的事件循环机制 和浏览器有什么不同? 在node中,事件循环表现出来的状态和浏览器大致相同,但是node有一套自己的模型. node事件循环依靠libuv引擎,node选择chrome ...

  4. JavaScript 事件循环:从起源到浏览器再到 Node

    浏览器渲染. ▐  案例分析 根据上述的处理模型,我们可以来看以下例子: console.log('script start'); setTimeout(function() { console.lo ...

  5. 5调用外部浏览器打开代码_浏览器事件循环

    浏览器运行过程中会同时面对多种任务,用户交互事件(鼠标.键盘).网络请求.页面渲染等.而这些任务不能是无序的,必须有个先来后到,浏览器内部需要一套预定的逻辑来有序处理这些任务,因此浏览器事件循环诞生了 ...

  6. 工作流 节点子线程_节点JS体系结构–单线程事件循环

    工作流 节点子线程 Today we will look into Node JS Architecture and Single Threaded Event Loop model. In our ...

  7. 聊聊Javascript的事件循环

    JavaScript.浏览器.事件之间的关系 JavaScript程序采用了异步事件驱动编程(Event-driven programming)模型,维基百科对它的解释是: 事件驱动程序设计(英语:E ...

  8. 深入理解JavaScript的事件循环(Event Loop) 一、什么是事件循环

    深入理解JavaScript的事件循环(Event Loop) 一.什么是事件循环 JS的代码执行是基于一种事件循环的机制,之所以称作事件循环,MDN给出的解释为因为它经常被用于类似如下的方式来实现 ...

  9. JavaScript事件循环

    大厂面试题分享 面试题库 后端面试题库 (面试必备) 推荐:★★★★★ 地址:前端面试题库 一.异步执行原理 1. 单线程的JavaScript 我们知道,JavaScript是一种单线程语言,它主要 ...

最新文章

  1. PHPStudy下Apache SSL证书安装教程
  2. Android横竖屏切换继续播放视频
  3. SAP Cloud for Customer的前端框架是如何基于SAP UI5框架开发的
  4. CentOS 下安装xdebug
  5. 2021软科世界大学学术排名发布!
  6. 为什么总是封板又打开涨停_警惕!如果股票涨停板反复打开说明了什么?
  7. java request 处理过程_小猿圈Java开发之从代码看spring mvc请求处理过程
  8. Alibaba之MySQL宝典_Alibaba之MySQL宝典流出!极致经典,堪称行业天花板
  9. 目前最全的R语言-图片的组合与拼接
  10. java中io创建文件和读取文件
  11. 路径规划—入门路径规划概念
  12. IDEA下配置安卓环境
  13. c语言怎么判断编码,C语言中判断一个char*是不是utf8编码
  14. R语言 交互式绘图echarts4r包Pictorial深探
  15. 如何开发微信小程序?(入门须知)
  16. windows10 禁用Device/Credential Guard解决方案
  17. WiFi基础学习到实战(三:WiFi网络“物理层”)
  18. Chia官方矿池测试版正式上线!?
  19. 使用设计模式出任CEO迎娶白富美(4)--走马上任,华丽转身
  20. 3D视觉|了解下工业上常见的3D相机

热门文章

  1. Jetson Tx1升级到ubuntu 20.04.5 LTS
  2. 通过Python Pandas计算亚马逊搜索关键词报告,计算点击共享和点击共享及转化比值
  3. 45 《定位》 -豆瓣评分8.3
  4. 欧盟更新玩具安全指令 2009/48/EC 协调标准
  5. 《深入解析IPv6(第3版)》——第10章 IPv6路由选择10.1 IPv6中的路由选择
  6. VS无法使用编辑并继续 及 警告LNK4075的解决方法
  7. X3100M3 RAID及操作系统支持
  8. Robots协议小记
  9. 页面加载慢该怎么办,一招教你解决。
  10. 企业培训讲师的惊天内幕,老板和培训经理们,你怎么看?