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 相关文章推荐
10个新的最有前途的JavaScript框架
Mar 12 Javascript
JavaScript通过字符串调用函数的实现方法
Mar 18 Javascript
JQuery判断checkbox是否选中及其它复选框操作方法合集
Jun 01 Javascript
浅谈js中调用函数时加不加括号的问题
Jul 28 Javascript
JS实现图片垂直居中显示小结
Dec 13 Javascript
vue router路由嵌套不显示问题的解决方法
Jun 17 Javascript
vue 2.0封装model组件的方法
Aug 03 Javascript
Scala解析Json字符串的实例详解
Oct 11 Javascript
Vue.js表单标签中的单选按钮、复选按钮和下拉列表的取值问题
Nov 22 Javascript
jQuery封装animate.css的实例
Jan 04 jQuery
Vue自定义组件的四种方式示例详解
Feb 28 Javascript
JS检测浏览器开发者工具是否打开的方法详解
Oct 02 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入门学习知识点四 PHP正则表达式基本应用
2011/07/14 PHP
php getcwd与dirname(__FILE__)区别详解
2016/09/24 PHP
载入进度条 效果
2006/07/08 Javascript
js资料prototype 属性
2007/03/13 Javascript
offsetParent 算法分析
2010/04/05 Javascript
动态改变div的z-index属性的简单实例
2013/08/08 Javascript
pace.js页面加载进度条插件
2015/09/29 Javascript
使用伪命名空间封装保护独自创建的对象方法
2016/08/04 Javascript
Bootstrap实现圆角、圆形头像和响应式图片
2016/12/14 Javascript
Angular的MVC和作用域
2016/12/26 Javascript
基于jQuery实现火焰灯效果导航菜单
2017/01/04 Javascript
原生JS实现获取及修改CSS样式的方法
2018/09/04 Javascript
nodejs require js文件入口,在package.json中指定默认入口main方法
2018/10/10 NodeJs
微信小程序时间轴实现方法示例
2019/01/14 Javascript
详解写好JS条件语句的5条守则
2019/02/28 Javascript
nodejs中实现修改用户路由功能
2019/05/24 NodeJs
Vue之Mixins(混入)的使用方法
2019/09/24 Javascript
基于Vue3.0开发轻量级手机端弹框组件V3Popup的场景分析
2020/12/30 Vue.js
python使用cStringIO实现临时内存文件访问的方法
2015/03/26 Python
Flask框架的学习指南之制作简单blog系统
2016/11/20 Python
Python实现的IP端口扫描工具类示例
2019/02/15 Python
Python编程快速上手——疯狂填词程序实现方法分析
2020/02/29 Python
Tensorflow中的dropout的使用方法
2020/03/13 Python
Python常用编译器原理及特点解析
2020/03/23 Python
查看keras各种网络结构各层的名字方式
2020/06/11 Python
Python通过zookeeper实现分布式服务代码解析
2020/07/22 Python
浅谈python锁与死锁问题
2020/08/14 Python
德国婴儿服装和婴儿用品购买网站:Baby Sweets
2019/12/08 全球购物
EJB3推出JPA的原因
2013/10/16 面试题
运动会解说词200字
2014/02/06 职场文书
违反校纪校规检讨书
2014/02/15 职场文书
音乐教学随笔感言
2014/02/19 职场文书
敬老院活动总结
2014/04/28 职场文书
资源环境与城乡规划管理专业自荐书
2014/09/26 职场文书
Spring Data JPA的Audit功能审计数据库的变更
2021/06/26 Java/Android
漫画「处刑少女的生存之道」第3卷封面公开
2022/03/21 日漫