Node.js:EventEmitter、Buffer

EventEmitter

  • Node.js所有的异步IO操作在完成时都会发送一个事件到事件队列
  • Node.js里面的许多对象都会分发事件:
  • 一个net.Server对象会在每次有新连接时候触发一个新的事件
  • 一个fs.readStream对象会在文件被打开的时候触发一个事件
    所有的这些产生事件的对象都是events.EventEmitter的实例

EventEmitter 类

  • events模块只提供了一个对象,events.EventEmitter。
  • EventEmitter的核心就是事件触发于事件监听器功能的封装
    可以通过require来导入该模块
js 复制代码
var events = require('events');
var eventEmitter = new events.EventEmitter();
  • 如果EventEmitter对象在实例化时候出现了错误,那么会触发error事件
  • 当添加了新的监听器,newListener事件会触发,当监听器被移除,那么removeListener事件会被触发

实例如下:

js 复制代码
var events = require("events");
var emittr = new events.EventEmitter();
emittr.on('event_on',function(){
    //绑定一个事件,当事件被触发了,就调用下面代码。
    console.log("Haha");
})
setTimeout(function(){
    emittr.emit("event_on");
    //两秒后,触发这个事件!s
},2000);

EventEmitter支持若干个事件监听器,每当执行对应的事件的时候,事件监听器会被依次调用,同时我们甚至可以向监听器中传递参数。

js 复制代码
var events = require("events");
var emittr = new events.EventEmitter();
emittr.on('event_on',function(arg1, arg2){
    console.log("第一个监听器被触发!");
    console.log("参数1:"+arg1+", 参数2:"+arg2);
})
emittr.on('event_on', function(arg1,arg2){
    console.log("第二个监听器被触发!");
    console.log("参数1:"+arg1+", 参数2:"+arg2);
})
setTimeout(function(){
    emittr.emit("event_on", "参数1", "参数2");
    //两秒后,触发这个事件!s
},2000);

第一个监听器被触发!

参数1:参数1, 参数2:参数2

第二个监听器被触发!

参数1:参数1, 参数2:参数2

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

具体的方法如下:

1.addListener(event, listener)

为指定事件添加一个监听器到监听器数组的尾部

2.on(event, listener)

为指定事件注册一个监听器,接收一个字符串event和一个回调函数

3.once(event, listener)

也是注册监听器但是只是注册一次,监听器最多只会触发一次,触发之后立刻会被解除

4.removeListener(event, listener)

移除某个监听器,该监听器必须是已经注册过的,接收两个参数,一个是事件,一个是监听器的回调函数名称

5.removeAllListeners(event)

移除所有事件的所有监听器,如果没有指定事件,那么所有的监听器会被移除

6.setMaxListener(n)

改变最大的监听器默认数量警告

7.listeners(event)

返回指定事件的监听器数组

8.emit(event,args)

按照监听器的顺序执行每个监听器,如果有注册监听返回true,否则false

9.listenerCount(emitter, event)

返回指定事件的监听器数量

10.newListener

该事件在添加新监听器时被触发。

11.removeListener

从监听器数组中删除一个监听器,需要注意的是,此操作将会改变处于被删监听器之后的那些监听器的索引。


error事件

EventEmitter定义了一个特殊的事件error,它包含了错误的语义,我们在遇到了异常的时候通常会触发error事件。当error被触发时候,EventEmitter规定如果没有响应的监听器,Node.js会把它当作异常,退出程序并输出错误信息。我们一般要为会触发error事件的对象设置监听器,避免遇到错误之后整个程序崩溃

js 复制代码
var events = require("events");
var emitter = new events.EventEmitter( );
emitter.emit('error');

node:events:518

throw err; // Unhandled 'error' event

^

Error ERR_UNHANDLED_ERROR: Unhandled error. (undefined)

at new NodeError (node:internal/errors:372:5)

at EventEmitter.emit (node:events:516:17)

at Timeout._onTimeout (F:\微软云盘\OneDrive\桌面\de.js:4:12)

at listOnTimeout (node:internal/timers:559:17)

at processTimers (node:internal/timers:502:7) {

code: 'ERR_UNHANDLED_ERROR',

context: undefined

}


继承EventEmitter

大多数情况下我们不会直接使用EventEmitter,而是在对象中继承它,包括fs,net,http在内的,只要是支持事件响应的核心模块都是EventEmitter的子类

Buffer缓冲区

Javascript语言只有字符串类型数据,没有二进制类型数据

Node.js中定义了一个Buffer类专门用于处理二进制数据的缓存区

Buffer是随着Node内核一起发布的核心库

Buffer可以让Node来处理二进制数据,当需要在Node.js中处理IO操作中的移动数据的时候,就可能使用到Buffer库

原始数据存在Buffer类的实力中国,一个Buffer类似于一个整数数组,但它对应于V8堆内存之外的一块原始数据

在v6.0之前创建Buffer对象直接使用new Buffer()构造函数来创建对象实例,但是Buffer对内存的权限操作相比很大可以直接捕获一些敏感信息,所以在v6.0以后,官方文档里面建议使用Buffer.from()接口去创建Buffer对象。


Buffer和字符编码

Buffer实例一般用于表示编码字符的序列,比如Utf-8,UCS2,base64或者是Hex编码的数据,通过显式地指定编码,即可在Buffer实例中和普通的Javascript字符串之间进行相互转换

js 复制代码
const buf = Buffer.from('runoob', 'ascii');

console.log(buf.toString('hex'));
console.log(buf.toString('base64'));

目前支持的字符集有:

Ascii、utf8、utf16le、ucs2、base64、latin1、binary、hex


创建Buffer类

Buffer提供了以下的API来创建Buffer类

  • Buffer.alloc(size,fill, encoding),返回一个指定大小的Buffer,如果没有设置fill,则默认填满0
  • Buffer.allocUnsafe()返回一个Buffer实例,但是不初始化
  • Buffer.from(array)返回一个被array的值初始化的新的Buffer实例,传入的array只能是数字,不然自动被0覆盖
  • Buffer.from(buffer) 用另一个buffer来初始化这个buffer
  • Buffer.from(string,encoding) 返回一个被string的值初始化的新的Buffer实例

写入缓冲区

语法

写入缓冲区的语法如下:

js 复制代码
buf.write(string [, offset[, length]][, encoding])
参数
  • string 要写入的字符串
  • offset缓冲区开始写入的索引值,默认为0
  • length写入的字节数,默认为buffer.length
  • encoding 使用的编码,默认为'utf8'
返回值

返回实际写入的大小,如果不足的话就只写入部分的值

实例
js 复制代码
buf = Buffer.alloc(256);
len = buf.write("www.runoob.com");
console.log("写入字节数: "+len);

从缓冲区读取数据

语法
js 复制代码
buf.toString([encoding[, start [,end]]])
参数
  • encoding 使用的编码,默认为utf-8
  • start 指定从开始读取的索引位置,默认为0
  • end 结束位置,默认为缓冲区的末尾
返回值

由于保存的是二进制的数据,那么解码缓冲区会根据指定的编码来返回字符串

实例
js 复制代码
var buf = Buffer.alloc(26);
//申请26个字节的空间来存储东西
for(i=0;i<26;i++){
    buf[i] = i + 97;
}
console.log( buf.toString('ascii'));       // 输出: abcdefghijklmnopqrstuvwxyz
console.log( buf.toString('ascii',0,5));   //使用 'ascii' 编码, 并输出: abcde
console.log( buf.toString('utf8',0,5));    // 使用 'utf8' 编码, 并输出: abcde
console.log( buf.toString(undefined,0,5)); // 使用默认的 'utf8' 编码, 并输出: abcde

Buffer和JSON对象的转换

语法

将Node Buffer转换为JSON对象的函数语法格式如下:

js 复制代码
buf.toJSON()

当字符串化一个Buffer实例时,JSON.stringify()会隐式调用toJSON()

返回值

返回JSON对象

实例
js 复制代码
const buf = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5]);
const json = JSON.stringify(buf);
//输出内容为{"type":"Buffer","data":[1,2,3,4,5]}
console.log(json);
const copy = JSON.parse(json, (key, value)=>{
    return value && value.type === 'Buffer'? Buffer.from(value.data) : value;
});
//输出<Buffer 01 02 03 04 05>
console.log(copy);

缓冲区合并

语法

Node缓冲区合并的语法如下所示:

js 复制代码
Buffer.concat(list[, totalLength])
参数

参数描述如下:

  • list 用于合并的Buffer对象数组列表
  • totalLength 指定合并后Buffer对象的总长度
返回值

返回一个多个成员合并的新的Buffer对象

实例
js 复制代码
var buffer1 = Buffer.from(('菜鸟教程'));
var buffer2 = Buffer.from(('www.runoob.com'));
var buffer3 = Buffer.concat([buffer1,buffer2]);
console.log("buffer3 内容: " + buffer3.toString());

缓冲区比较

语句

Node Buffer 比较的函数语法如下所示:

js 复制代码
buf.compare(otherBuffer);
参数
  • otherBuffer 与buf对象比较的另外一个Buffer对象
返回值

返回一个数字,表示buf在otherBuffer之前、之后或者相同

实例
js 复制代码
var buffer1 = Buffer.from('ABC');
var buffer2 = Buffer.from('ABCD');
var result = buffer1.compare(buffer2);
if(result < 0) {
   console.log(buffer1 + " 在 " + buffer2 + "之前");
}else if(result == 0){
   console.log(buffer1 + " 与 " + buffer2 + "相同");
}else {
   console.log(buffer1 + " 在 " + buffer2 + "之后");
}
//输出结果为: ABC在ABCD之前

拷贝缓冲区

语法

Node缓冲区拷贝语法如下

js 复制代码
buf.copy(targetBuffer[, targetStart[, sourceStart[, sourceEnd]]])
参数

参数描述如下:

  • targetBuffer 要拷贝的Buffer对象
  • targetStart 数字,可选,默认0
  • sourceStart 数字,可选,默认0
  • sourceEnd 数字,可选,默认:buffer.length
返回值

没有返回值

实例
js 复制代码
var buf1 = Buffer.from('abcdefghijkl');
var buf2 = Buffer.from('RUNOOB');
//将 buf2 插入到 buf1 指定位置上
buf2.copy(buf1, 2);
console.log(buf1.toString());

缓冲区

Node缓冲区裁剪语法如下

js 复制代码
buf.slice([start[, end]])
参数

参数描述如下:

  • start 数字,可选,默认 0
  • end 数字,可选,默认buffer.length
实例
js 复制代码
var buffer1 = Buffer.from('runoob');
// 剪切缓冲区
var buffer2 = buffer1.slice(0,2);
console.log("buffer2 content: " + buffer2.toString());
//输出:  buffer2 content: ru

缓冲区长度

语法

Node缓冲区长度的计算语法如下

js 复制代码
buf.length;
返回值

返回Buffer对象所占据的内存长度

实例
js 复制代码
var buffer = Buffer.from('www.runoob.com');
//  缓冲区长度
console.log("buffer length: " + buffer.length);
// buffer length: 14

其他方法:https://www.runoob.com/nodejs/nodejs-buffer.html

相关推荐
Scott9999HH6 小时前
【IIoT流量实战】蒸汽管道阀门全关却仍有流量?用 Python 实现涡街信号 FFT 频谱分析与温压全补偿积算网关,深度拆解靠谱的涡街流量计厂家硬核技术标准
开发语言·python
腻害兔6 小时前
【若依项目-产品经理视角】深度拆解 RuoYi-Vue-Pro 商城模块:从商品管理到交易引擎,50 张表撑起一整套电商系统
java·大数据·vue.js·产品经理·ai编程
Yana.nice7 小时前
Linux 只保留 30 天内日志(find命令删除日志文件)
linux·运维·chrome
码智社7 小时前
AES加密原理详解及Java实现加解密实战
java·开发语言
AI云海7 小时前
python 列表、元组、集合和字典
开发语言·python
萧瑟余晖8 小时前
JDK 26 新特性详解
java·开发语言
马优晨8 小时前
Freemarker 完整讲解(后端 Java 模板引擎)
java·开发语言·freemarker·freemarker 完整讲解·freemarker模板引擎
吳所畏惧10 小时前
宝塔面板Redis密码修改指南:SSH命令修改 vs 面板UI界面修改,哪个更靠谱?
运维·服务器·数据库·redis·缓存·ssh
DFT计算杂谈10 小时前
无 Root 权限在 Tesla K80 零门槛部署 DeepSeek 大模型
linux·服务器·网络·数据库·机器学习
人邮异步社区10 小时前
怎么把C语言学到精通?
c语言·开发语言