node总结之事件循环了解下
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总结之事件循环了解下相关推荐
- Node.js event loop 和 JS 浏览器环境下的事件循环的区别
Node.js event loop 和 JS 浏览器环境下的事件循环的区别: 1.线程与进程: JS 是单线程执行的,指的是一个进程里只有一个主线程,那到底什么是线程?什么是进程? 进程是 CPU ...
- Node - 异步IO和事件循环
前言 学习Node就绕不开异步IO, 异步IO又与事件循环息息相关, 而关于这一块一直没有仔细去了解整理过, 刚好最近在做项目的时候, 有了一些思考就记录了下来, 希望能尽量将这一块的知识整理清楚, ...
- JavaScript执行机制-node事件循环
node环境下的事件循环机制 和浏览器有什么不同? 在node中,事件循环表现出来的状态和浏览器大致相同,但是node有一套自己的模型. node事件循环依靠libuv引擎,node选择chrome ...
- JavaScript 事件循环:从起源到浏览器再到 Node
浏览器渲染. ▐ 案例分析 根据上述的处理模型,我们可以来看以下例子: console.log('script start'); setTimeout(function() { console.lo ...
- 5调用外部浏览器打开代码_浏览器事件循环
浏览器运行过程中会同时面对多种任务,用户交互事件(鼠标.键盘).网络请求.页面渲染等.而这些任务不能是无序的,必须有个先来后到,浏览器内部需要一套预定的逻辑来有序处理这些任务,因此浏览器事件循环诞生了 ...
- 工作流 节点子线程_节点JS体系结构–单线程事件循环
工作流 节点子线程 Today we will look into Node JS Architecture and Single Threaded Event Loop model. In our ...
- 聊聊Javascript的事件循环
JavaScript.浏览器.事件之间的关系 JavaScript程序采用了异步事件驱动编程(Event-driven programming)模型,维基百科对它的解释是: 事件驱动程序设计(英语:E ...
- 深入理解JavaScript的事件循环(Event Loop) 一、什么是事件循环
深入理解JavaScript的事件循环(Event Loop) 一.什么是事件循环 JS的代码执行是基于一种事件循环的机制,之所以称作事件循环,MDN给出的解释为因为它经常被用于类似如下的方式来实现 ...
- JavaScript事件循环
大厂面试题分享 面试题库 后端面试题库 (面试必备) 推荐:★★★★★ 地址:前端面试题库 一.异步执行原理 1. 单线程的JavaScript 我们知道,JavaScript是一种单线程语言,它主要 ...
最新文章
- PHPStudy下Apache SSL证书安装教程
- Android横竖屏切换继续播放视频
- SAP Cloud for Customer的前端框架是如何基于SAP UI5框架开发的
- CentOS 下安装xdebug
- 2021软科世界大学学术排名发布!
- 为什么总是封板又打开涨停_警惕!如果股票涨停板反复打开说明了什么?
- java request 处理过程_小猿圈Java开发之从代码看spring mvc请求处理过程
- Alibaba之MySQL宝典_Alibaba之MySQL宝典流出!极致经典,堪称行业天花板
- 目前最全的R语言-图片的组合与拼接
- java中io创建文件和读取文件
- 路径规划—入门路径规划概念
- IDEA下配置安卓环境
- c语言怎么判断编码,C语言中判断一个char*是不是utf8编码
- R语言 交互式绘图echarts4r包Pictorial深探
- 如何开发微信小程序?(入门须知)
- windows10 禁用Device/Credential Guard解决方案
- WiFi基础学习到实战(三:WiFi网络“物理层”)
- Chia官方矿池测试版正式上线!?
- 使用设计模式出任CEO迎娶白富美(4)--走马上任,华丽转身
- 3D视觉|了解下工业上常见的3D相机
热门文章
- Jetson Tx1升级到ubuntu 20.04.5 LTS
- 通过Python Pandas计算亚马逊搜索关键词报告,计算点击共享和点击共享及转化比值
- 45 《定位》 -豆瓣评分8.3
- 欧盟更新玩具安全指令 2009/48/EC 协调标准
- 《深入解析IPv6(第3版)》——第10章 IPv6路由选择10.1 IPv6中的路由选择
- VS无法使用编辑并继续 及 警告LNK4075的解决方法
- X3100M3 RAID及操作系统支持
- Robots协议小记
- 页面加载慢该怎么办,一招教你解决。
- 企业培训讲师的惊天内幕,老板和培训经理们,你怎么看?