探索node之事件循环的实现


Posted in Javascript onOctober 30, 2020

事件循环

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

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

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

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

进程:CPU执行任务的模块

线程:模块中的最小单元

举个通俗的例子:

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

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

事件驱动程序

Node.js使用事件驱动模型,当web server接收到请求,就把它关闭然后进行处理,然后去服务下一个web请求
当这个请求完成,它被放回处理队列,当到达队列开头,这个结果就返回给用户。

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

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

探索node之事件循环的实现

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

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

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

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

//通过程序触发事件
eventEmitter.emit('eventName')

示例:

//引入events模块
let events = require('events');

//创建eventEmitter对象
let eventEmitter = new events.EventEmitter();

//创建事件处理程序
let connectHandle = function connected() {
 console.log('连接成功');
 //触发data_received事件
 eventEmitter.emit('data_received')
}

//绑定connection事件处理程序
eventEmitter.on('connection', connectHandle);

//使用匿名函数绑定data_received事件
eventEmitter.on('data_received', function () {
 console.log('数据接收成功');
})

//触发connecttion事件
eventEmitter.emit('connection');
console.log('程序执行完毕');


// 执行结果:
// 连接成功
// 数据接收成功
// 程序执行完毕

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

EventEmitter

node.js所有的异步I/O操作在完成时都会发送一个事件到事件队列

node.js里面的许多对象都会分发事件:一个net.Server对象会在每次有新连接时触发的一个事件,一个fs.readStream对象会在文件被打开的时候触发一个事件。所有这些产生事件的对象都是events.EventEmitter的实例

events 模块只提供了一个对象: events.EventEmitter。EventEmitter 的核心就是事件触发与事件监听器功能的封装。

EventEmitter 对象如果在实例化时发生错误,会触发 error 事件。当添加新的监听器时,newListener 事件会触发,当监听器被移除时,removeListener 事件被触发。

简单用法

var EventEmitter = require('events').EventEmitter; 
var event = new EventEmitter(); 
event.on('some_event', function() { 
  console.log('some_event 事件触发'); 
}); 
setTimeout(function() { 
  event.emit('some_event'); 
}, 1000);

运行这段代码,1 秒后控制台输出了 ‘some_event 事件触发'。
其原理是 event 对象注册了事件 some_event 的一个监听器,
然后我们通过 setTimeout 在 1000 毫秒以后向 event 对象发送事件 some_event,此时会调用some_event 的监听器。

EventEmitter 的每个事件由一个事件名和若干个参数组成,事件名是一个字符串,通常表达一定的语义。对于每个事件,EventEmitter 支持 若干个事件监听器。

当事件触发时,注册到这个事件的事件监听器被依次调用,事件参数作为回调函数参数传递。

var events = require('events'); 
var emitter = new events.EventEmitter(); 
emitter.on('someEvent', function(arg1, arg2) { 
  console.log('listener1', arg1, arg2); 
}); 
emitter.on('someEvent', function(arg1, arg2) { 
  console.log('listener2', arg1, arg2); 
}); 
emitter.emit('someEvent', 'arg1 参数', 'arg2 参数'); 
//输出:
// listener1 arg1 参数 arg2 参数
// listener2 arg1 参数 arg2 参数

以上例子中,emitter 为事件 someEvent 注册了两个事件监听器,然后触发了 someEvent 事件。

运行结果中可以看到两个事件监听器回调函数被先后调用。 这就是EventEmitter最简单的用法。

EventEmitter 提供了多个属性,如 on 和 emit。on 函数用于绑定事件函数,emit 属性用于触发一个事件。、

EventEmitter属性

探索node之事件循环的实现

测试

/*
 * @Author: angula
 * @Date: 2020-09-21 22:29:18
 * @LastEditTime: 2020-09-22 11:27:56
 * @FilePath: \JS\Github-前端知识总结仓库\studySummary\Node.js学习笔记\事件循环\index2.js
 */
let events = require('events');
let eventEmitter = new events.EventEmitter();

// 监听器1
let listener1 = function listener1() {
 console.log('监听器listener1启动。。。');
}

// 监听器2
let listener2 = function listener2() {
 console.log('监听器listener2启动。。。');
}

// 绑定connection事件,处理函数为listener1
eventEmitter.addListener('connection', listener1);
// 绑定connection事件,处理函数为listener2
eventEmitter.on('connection', listener2);


//类,返回监听器的数量

let eventListeners = eventEmitter.listenerCount('connection');
console.log(eventListeners + '个监听器监听连接事件。');


//处理connection事件
eventEmitter.emit('connection');

// 移除绑定的listener1
eventEmitter.removeListener('connection', listener1);
console.log('listener1不再受监听');

//触发连接事件
eventEmitter.emit('connection');

eventListeners = eventEmitter.listenerCount('connection');
console.log(eventListeners + '个监听器连接事件');

console.log('程序执行完毕');

执行结果:

探索node之事件循环的实现

到此这篇关于探索node之事件循环的实现的文章就介绍到这了,更多相关node 事件循环内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
javascript抖动元素的小例子
Oct 28 Javascript
node.js中的buffer.copy方法使用说明
Dec 14 Javascript
javascript运动详解
Jul 06 Javascript
JSON字符串转JSON对象
Jul 31 Javascript
浅析JS动态创建元素【两种方法】
Apr 20 Javascript
js print打印网页指定区域内容的简单实例
Nov 01 Javascript
微信小程序 ES6Promise.all批量上传文件实现代码
Apr 14 Javascript
vue项目中使用fetch的实现方法
Apr 25 Javascript
使用js实现一个简单的滚动条过程解析
Sep 10 Javascript
小程序input数据双向绑定实现方法
Oct 17 Javascript
taro小程序添加骨架屏的实现代码
Nov 15 Javascript
JavaScript ECMA-262-3 深入解析(二):变量对象实例详解
Apr 25 Javascript
使用TS来编写express服务器的方法步骤
Oct 29 #Javascript
微信小程序将页面按钮悬浮固定在底部的实现代码
Oct 29 #Javascript
vue3.0搭配.net core实现文件上传组件
Oct 29 #Javascript
使用jQuery实现购物车
Oct 29 #jQuery
ant design中upload组件上传大文件,显示进度条进度的实例
Oct 29 #Javascript
react使用antd表单赋值,用于修改弹框的操作
Oct 29 #Javascript
node.js爬虫框架node-crawler初体验
Oct 29 #Javascript
You might like
PHP 和 MySQL 基础教程(三)
2006/10/09 PHP
php Smarty初体验二 获取配置信息
2011/08/08 PHP
基于PHP技术开发客服工单系统
2016/01/06 PHP
CI分页类首页、尾页不显示的解决方法
2016/03/28 PHP
yii2简单使用less代替css示例
2017/03/10 PHP
Laravel6.0.4中将添加计划任务事件的方法步骤
2019/10/15 PHP
javascript css在IE和Firefox中区别分析
2009/02/18 Javascript
基于jquery实现的移入页面上空文本框时,让它变为焦点,移出清除焦点
2011/07/26 Javascript
jQuery中fadeIn、fadeOut、fadeTo的使用方法(图片显示与隐藏)
2013/05/08 Javascript
jQuery中map()方法用法实例
2015/01/06 Javascript
js实现横向百叶窗效果网页切换动画效果的方法
2015/03/02 Javascript
基于jquery实现鼠标滚轮驱动的图片切换效果
2015/10/26 Javascript
Bootstrap幻灯片轮播图支持触屏左右手势滑动的实现方法
2016/10/13 Javascript
jQuery使用zTree插件实现可拖拽的树示例
2017/09/23 jQuery
基于JS实现一个随机生成验证码功能
2019/05/29 Javascript
VUE实现图片验证码功能
2020/11/18 Javascript
vue之debounce属性被移除及处理详解
2019/11/13 Javascript
vue-socket.io跨域问题有效解决方法
2020/02/11 Javascript
JS数组reduce()方法原理及使用技巧解析
2020/07/14 Javascript
JavaScript实现鼠标经过表格某行时此行变色
2020/11/20 Javascript
Python中类的定义、继承及使用对象实例详解
2015/04/30 Python
Python图像处理之简单画板实现方法示例
2018/08/30 Python
Python使用pyautogui模块实现自动化鼠标和键盘操作示例
2018/09/04 Python
Python requests.post方法中data与json参数区别详解
2020/04/30 Python
keras的ImageDataGenerator和flow()的用法说明
2020/07/03 Python
python用700行代码实现http客户端
2021/01/14 Python
css3实例教程 一款纯css3实现的环形导航菜单
2014/10/20 HTML / CSS
五个2015 年最佳HTML5 框架
2015/11/11 HTML / CSS
新秀丽拉杆箱美国官方网站:Samsonite美国
2016/07/25 全球购物
Everything But Water官网:美国泳装品牌
2019/03/17 全球购物
应届生英语教师求职信
2013/11/05 职场文书
办公设备采购方案
2014/03/16 职场文书
班主任师德师风自我剖析材料
2014/10/02 职场文书
3.15消费者权益日活动总结
2015/02/09 职场文书
青年人初次创业的“五不要”
2019/08/23 职场文书
MySQL的Query Cache图文详解
2021/07/01 MySQL