node.js使用stream模块实现自定义流示例


Posted in Javascript onFebruary 13, 2020

本文实例讲述了node.js使用stream模块实现自定义流。分享给大家供大家参考,具体如下:

有些时候我们需要自定义一些流,来操作特殊对象,node.js中为我们提供了一些基本流类。

我们新创建的流类需要继承四个基本流类之一(stream.Writeable,stream.Readable,stream.Duplex,stream.Transform),并确保调用了父类构造函数。

一、实现自定义的可读流

实现可读流需继承 stream.Readable,并实现 readable._read() 方法。

下面的代码我们实现了一个从数组中读取数据的流

const {Readable} = require('stream');
//这里我们自定义了一个用来读取数组的流
class ArrRead extends Readable {
  constructor(arr, opt) {
    //注意这里,需调用父类的构造函数
    super(opt);
    this.arr = arr;
    this.index = 0;
  }
  //实现 _read() 方法
  _read(size) {
    //如果当前下标等于数组长度,说明数据已经读完
    if (this.index == this.arr.length) {
      this.push(null);
    } else {
      this.arr.slice(this.index, this.index + size).forEach((value) => {
        this.push(value.toString());
      });
      this.index += size;
    }
  }
}
let arr = new ArrRead([1, 2, 3, 4, 5, 6, 7, 8, 9, 0], {
  highWaterMark: 2
});
//这样当我们监听 'data' 事件时,流会调用我们实现的 _read() 方法往缓冲区中读取数据
//然后提供给消费者
arr.on('data', function (data) {
  console.log(data.toString());
});

二、实现自定义的可写流

实现可写流必须继承 stream.Writeable ,并实现 writeable._write() 方法。writable._writev() 方法是可选的。

const {Writable} = require('stream');
//这里我们自定义了一个用来写入数组的流
class ArrWrite extends Writable {
  constructor(arr, opt) {
    super(opt);
    this.arr = arr;
  }
  //实现 _write() 方法
  _write(chunk, encoding, callback) {
    this.arr.push(chunk.toString());
    callback();
  }
}
let data = [];
let arr = new ArrWrite(data, {
  highWaterMark: 3
});
arr.write('1');
arr.write('2');
arr.write('3');
console.log(data);

三、实现自定义的可读可写流

可读可写流必须继承 stream.Duplex,并实现 readable._read() 和 writable._write() 方法。

const {Duplex} = require('stream');
//这里我们自定义了一个用来写读可写数组的流
class ArrReadWrite extends Duplex {
  constructor(arr, opt) {
    super(opt);
    this.arr = arr;
    this.index = 0;
  }
  //实现 _write() 方法
  _write(chunk, encoding, callback) {
    this.arr.push(chunk.toString());
    callback();
  }
  //实现 _read() 方法
  _read(size) {
    //如果当前下标等于数组长度,说明数据已经读完
    if (this.index == this.arr.length) {
      this.push(null);
    } else {
      this.arr.slice(this.index, this.index + size).forEach((value) => {
        this.push(value.toString());
      });
      this.index += size;
    }
  }
}
let data = [];
let arrWR = new ArrReadWrite(data, {
  highWaterMark: 3
});
//往流中写入数据
arrWR.write('1');
arrWR.write('2');
arrWR.write('3');
console.log(data);
//往流中读取数据
console.log(arrWR.read(2).toString());
console.log(arrWR.read(2).toString());

四、自定义的转换流

转换流必须继承 stream.Transform,需实现 transform._transform() 方法。

const {Transform} = require('stream');
//这里我们自定义了一个用来转换数组的流
class Trans extends Transform {
  constructor(opt) {
    super(opt);
  }
  _transform(chunk, encoding, callback) {
    //将转换后的数据输出到可读流
    this.push(chunk.toString().toUpperCase());
    //参数一是Error对象
    //参数二如果传入,会被转发到 readable.push()
    callback();
  }
}
let t = new Trans({
  highWaterMark: 3
});
t.on('data', function (data) {
  console.log(data.toString());
});
t.write('a');
t.write('b');
t.write('c');

转换流就是将读取到的数据做些计算然后输出。转换流既可以作为可读流,又可以作为可写流。

const {Transform} = require('stream');
//这里我们自定义了一个用来转换数组的流
class Trans extends Transform {
  constructor(opt) {
    super(opt);
  }
  _transform(chunk, encoding, callback) {
    //将转换后的数据输出到可读流
    this.push(chunk.toString().toUpperCase());
    //参数一是Error对象
    //参数二如果传入,会被转发到 readable.push()
    callback();
  }
}
let t = new Trans({
  highWaterMark: 3
});
t.on('data', function (data) {
  console.log('data', data.toString());
});
//stdin.pipe(t) 表示将我们的标准输入写入到我的转换流 t 中,此时 t 是可写流。
//pipe(process.stdout) 表示将转换流 t 中的数据读取到标准输出中,此时 t 是可读流。
process.stdin.pipe(t).pipe(process.stdout);

希望本文所述对大家node.js程序设计有所帮助。

Javascript 相关文章推荐
[转]JS宝典学习笔记
Feb 07 Javascript
javascript实现面向对象类的功能书写技巧
Mar 07 Javascript
fancybox1.3.1 基于Jquery的插件在IE中图片显示问题
Oct 01 Javascript
Windows8下搭建Node.js开发环境教程
Sep 03 Javascript
js实现拖拽效果
Feb 12 Javascript
Javascript自定义事件详解
Jan 13 Javascript
JavaScript高阶函数_动力节点Java学院整理
Jun 28 Javascript
基于jQuery实现手风琴菜单、层级菜单、置顶菜单、无缝滚动效果
Jul 20 jQuery
Vue Cli与BootStrap结合实现表格分页功能
Aug 18 Javascript
Vue中Table组件Select的勾选和取消勾选事件详解
Mar 19 Javascript
vue.js实现备忘录demo
Jun 26 Javascript
vue项目里面引用svg文件并给svg里面的元素赋值
Aug 17 Javascript
Vue export import 导入导出的多种方式与区别介绍
Feb 12 #Javascript
JS FormData对象使用方法实例详解
Feb 12 #Javascript
JS+HTML实现自定义上传图片按钮并显示图片功能的方法分析
Feb 12 #Javascript
微信小程序实现树莓派(raspberry pi)小车控制
Feb 12 #Javascript
JavaScript 替换所有匹配内容及正则替换方法
Feb 12 #Javascript
使用webpack搭建pixi.js开发环境
Feb 12 #Javascript
十分钟教你上手ES2020新特性
Feb 12 #Javascript
You might like
php绘图中显示不出图片的原因及解决
2014/03/05 PHP
php多功能图片处理类分享(php图片缩放类)
2014/03/14 PHP
WordPress中用于检索模版的相关PHP函数使用解析
2015/12/15 PHP
PHP面向对象程序设计方法实例详解
2016/12/24 PHP
详解PHP中的序列化、反序列化操作
2017/03/21 PHP
通过隐藏option实现select的联动效果
2009/11/10 Javascript
Visual Studio中的jQuery智能提示设置方法
2010/03/27 Javascript
js判断两个日期是否相等的方法
2013/09/10 Javascript
浅谈jQuery中的事件
2015/03/23 Javascript
Ajax跨域实现代码(后台jsp)
2017/01/21 Javascript
Require.JS中的几种define定义方式示例
2017/06/01 Javascript
浅谈JS中this在各个场景下的指向
2019/08/14 Javascript
vue keep-alive列表页缓存 详情页返回上一页不刷新,定位到之前位置
2019/11/26 Javascript
python备份文件以及mysql数据库的脚本代码
2013/06/10 Python
python线程锁(thread)学习示例
2013/12/04 Python
12步入门Python中的decorator装饰器使用方法
2016/06/20 Python
TensorFlow神经网络优化策略学习
2018/03/09 Python
python 计算一个字符串中所有数字的和实例
2019/06/11 Python
pybind11和numpy进行交互的方法
2019/07/04 Python
处理python中多线程与多进程中的数据共享问题
2019/07/28 Python
Python如何读取文件中图片格式
2020/01/13 Python
Python如何转换字符串大小写
2020/06/04 Python
html5 Canvas画图教程(10)—把面拆成线条模拟出圆角矩形
2013/01/09 HTML / CSS
兰蔻加拿大官方网站:Lancome加拿大
2016/08/05 全球购物
韩国著名的在线综合购物网站:Akmall
2016/08/07 全球购物
Expedia加拿大官方网站:加拿大最大的在线旅游提供商
2017/12/31 全球购物
教师演讲稿范文
2014/01/08 职场文书
留学推荐信怎么写
2014/01/25 职场文书
小学生家长评语大全
2014/02/10 职场文书
运动会800米加油稿
2014/02/22 职场文书
联欢晚会主持词
2014/03/25 职场文书
小学节能减排倡议书
2014/05/15 职场文书
白岩松演讲
2014/05/21 职场文书
帮一个朋友写的求职信
2014/08/09 职场文书
2015年学校政教处工作总结
2015/05/26 职场文书
宪法宣传标语100条
2019/10/15 职场文书