概述

常见的自定义流有四种,Readable(可读流)、Writable(可写流)、Duplex(双工流)和 Transform(转换流),常见的自定义流应用有 HTTP 请求、响应,crypto 加密,进程 stdin 通信等等。

stream 模块介绍

在 NodeJS 中要想实现自定义流,需要依赖模块 stream,直接引入,不需下载,所有种类的流都是继承这个模块内部提供的对应不同种类的类来实现的。

实现一个自定义可读流 Readable

1、创建自定义可读流的类 MyRead

实现自定义可读流需创建一个类为 MyRead,并继承 stream 中的 Readable 类,重写 _read 方法,这是所有自定义流的固定套路。

let { Readable } = require("stream");

// 创建自定义可读流的类
class MyRead extends Readable {
constructor() {
super();
this.index = 0;
} // 重写自定义的可读流的 _read 方法
_read() {
this.index++;
this.push(this.index + ""); if (this.index === 3) {
this.push(null);
}
}
}
复制代码

我们自己写的 _read 方法会先查找并执行,在读取时使用 push 方法将数据读取出来,直到 push 的值为 null 才会停止,否则会认为没有读取完成,会继续调用 _read

2、验证自定义可读流

let myRead = new MyRead();

myRead.on("data", data => {
console.log(data);
}); myRead.on("end", function() {
console.log("读取完成");
}); // <Buffer 31>
// <Buffer 32>
// <Buffer 33>
// 读取完成
复制代码

实现一个自定义可写流 Writable

1、创建自定义可写流的类 MyWrite

创建一个类名为 MyWrite,并继承 stream 中的 Writable 类,重写 _write 方法。

let { Writable } = require("stream");

// 创建自定义可写流的类
class MyWrite extends Writable {
// 重写自定义的可写流的 _write 方法
_write(chunk, encoding, callback)) {
callback(); // 将缓存区写入文件
}
}
复制代码

写入内容时默认第一次写入直接写入文件,后面的写入都写入缓存区,如果不调用 callback 只能默认第一次写入文件,调用 callback 会将缓存区清空并写入文件。

2、验证自定义可写流

let myWrite = new MyWrite();

myWrite.write("hello", "utf8", () => {
console.log("hello ok");
}); myWrite.write("world", "utf8", () => {
console.log("world ok");
}); // hello ok
// world ok
复制代码

实现一个自定义双工流 Duplex

1、创建自定义可双工流的类 MyDuplex

双工流的可以理解为即可读又可写的流,创建一个类名为 MyDuplex,并继承 stream 中的 Duplex 类,由于双工流即可读又可写,需重写 _read_write 方法。

let { Duplex } = require("stream");

// 创建自定义双工流的类
class MyDuplex extends Duplex { // 重写自定义的双工流的 _read 方法
_read() {
this.push("123");
this.push(null);
} // 重写自定义的双工流的 _write 方法
_write(chunk, encoding, callback)) {
callback();
}
}
复制代码

双工流分别具备 ReadableWritable 的功能,但是读和写互不影响,互不关联。

2、验证自定义双工流

let myDuplex = new MyDuplex();

myDuplex.on("readable", () => {
console.log(myDuplex.read(1), "----");
}); setTimeout(() => {
myDuplex.on("data", data => {
console.log(data, "xxxx");
});
}, 3000); // <Buffer 31> ----
// <Buffer 32> xxxx
// <Buffer 32> ----
// <Buffer 33> xxxx
复制代码

如果 readabledata 两种读取方式都使用默认先通过 data 事件读取,所以一般只选择一个,不要同时使用,可读流的特点是读取数据被消耗掉后就丢失了(缓存区被清空),如果非要两个都用可以加一个定时器(绝对不要这样写)。

实现一个自定义转化流 Transform

1、创建自定义可转化流的类 MyTransform

转化流的意思是即可以当作可读流,又可以当作可写流,创建一个类名为 MyTransform,并继承 stream 中的 Transform 类,重写 _transform 方法,该方法的参数和 _write 相同。

let { Transform } = require('stream');

// 创建自定义转化流的类
class MyTransform extends Transform { // 重写自定义的转化流的 _transform 方法
_transform(chunk, encoding, callback)) {
console.log(chunck.toString.toUpperCase());
callback();
this.push('123');
}
}
复制代码

在自定义转化流的 _transform 方法中,读取数据的 push 方法和 写入数据的 callback 都可以使用。

2、验证自定义转化流

// demo.js
let myTransForm = new MyTransform(); // 使用标准输入
process.stdin.pipe(myTransForm).pipe(process.stdin);
复制代码

打开命令行窗口执行 node demo.js,然后输入 abc,会在命令窗口输出 ABC123,其实转换流先作为一个可写流被写入到标准输入中,而此时 stdin 的作用是读流,即读取用户的输入,读取后转换流作为一个可读流调用 pipe,将用户输入的信息通过标准输出写到命令行窗口,此时 stdout 的作用是写流。

总结

自定义流最常见的种类在上面都已经涵盖了,真正的在开发中用到的不多,如果需要写一个自定义流应该比上面的复杂很多,本文主要目的是认识什么是自定义流,并了解写一个自定义流的基本套路。

最后,顺便传播一个好消息:

想上线自己的后台系统或者做自己网站的,机会来了,腾讯云现做活动,新手福利1000减750,云服务器最低2折,云服务器1核2G内存50G硬盘3年最低只要600元!戳此了解详情


作者:PandaShen
链接:https://juejin.im/post/5b5e2061e51d45339e7ed83c
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

NodeJS —— 自定义流的实现的更多相关文章

  1. activiti自定义流程之Spring整合activiti-modeler5.16实例(九):历史任务查询

    注:(1)环境搭建:activiti自定义流程之Spring整合activiti-modeler5.16实例(一):环境搭建        (2)创建流程模型:activiti自定义流程之Spring ...

  2. activiti自定义流程之Spring整合activiti-modeler5.16实例(八):完成个人任务

    注:(1)环境搭建:activiti自定义流程之Spring整合activiti-modeler5.16实例(一):环境搭建        (2)创建流程模型:activiti自定义流程之Spring ...

  3. activiti自定义流程之Spring整合activiti-modeler5.16实例(七):任务列表展示

    注:(1)环境搭建:activiti自定义流程之Spring整合activiti-modeler5.16实例(一):环境搭建        (2)创建流程模型:activiti自定义流程之Spring ...

  4. activiti自定义流程之Spring整合activiti-modeler5.16实例(六):启动流程

    注:(1)环境搭建:activiti自定义流程之Spring整合activiti-modeler5.16实例(一):环境搭建        (2)创建流程模型:activiti自定义流程之Spring ...

  5. activiti自定义流程之Spring整合activiti-modeler5.16实例(五):流程定义列表

    注:(1)环境搭建:activiti自定义流程之Spring整合activiti-modeler5.16实例(一):环境搭建        (2)创建流程模型:activiti自定义流程之Spring ...

  6. activiti自定义流程之Spring整合activiti-modeler5.16实例(四):部署流程定义

    注:(1)环境搭建:activiti自定义流程之Spring整合activiti-modeler5.16实例(一):环境搭建        (2)创建流程模型:activiti自定义流程之Spring ...

  7. activiti自定义流程之Spring整合activiti-modeler5.16实例(三):流程模型列表展示

    注:(1)环境搭建:activiti自定义流程之Spring整合activiti-modeler5.16实例(一):环境搭建        (2)创建流程模型:activiti自定义流程之Spring ...

  8. activiti自定义流程之Spring整合activiti-modeler5.16实例(二):创建流程模型

    注:(1)环境搭建:activiti自定义流程之Spring整合activiti-modeler5.16实例(一):环境搭建 1.maven导包,这里就没有什么多的好说了,直接代码: <depe ...

  9. NodeJS Stream流

    NodeJS Stream流 流数据在网络通信中至关重要,nodeJS用Stream提供了一个抽象接口,node中有很多对象实现了这个接口,提供统一的操作体验 基本流类型 NodeJS中,Stream ...

随机推荐

  1. linux以下安装dnw

    [root@embedded secbulk]# make -C /lib/modules/`uname -r`/build M=`pwd` modules make: *** /lib/module ...

  2. maven 手动构建项目

    maven 手动构建项目 在空目录下面: D:\test>mvn -B archetype:generate -DarchetypeGroupId=org.apache.maven.archet ...

  3. 【c语言】统计一个数字在排序数组中出现的次数

    // 题目:统计一个数字在排序数组中出现的次数. //  比如:排序数组{1.2,3,3,3,3,4.5}和数字3,因为3出现了4次.因此输出4 有一种最简单的算法,遍历.可是有比它效率更高的 先看遍 ...

  4. PHP导入和导出CSV文件

    CREATE TABLE `student` ( `id` ) NOT NULL auto_increment, `name` varchar() NOT NULL, `sex` varchar() ...

  5. 【v2.x OGE-example 第三节 播放精灵动画】

    1. 位置:Drawing_example --> SpriteAnimated 2. 类名:SpriteAnimated 3.利用AnimatedSprite动画精灵类能够实现多种多种动作. ...

  6. HDOJ 5387 Clock 水+模拟

    Clock Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Subm ...

  7. C++ - RTTI(RunTime Type Information)执行时类型信息 具体解释

    RTTI(RunTime Type Information)执行时类型信息 具体解释 本文地址: http://blog.csdn.net/caroline_wendy/article/details ...

  8. Python正則表達式小结(1)

    学习一段python正則表達式了, 对match.search.findall.finditer等函数作一小结  以下以一段网页为例,用python正則表達式作一个范例: strHtml = '''& ...

  9. 使用mpxj读取MSPrjoect

    import java.util.ArrayList; import java.util.Calendar; import java.util.Hashtable; import java.util. ...

  10. Hibernate- Criteria 简易

    package cn.demo; import java.util.List; import org.hibernate.Criteria; import org.hibernate.Session; ...