NodeJS —— 自定义流的实现

 

概述

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


stream 模块介绍

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

实现一个自定义可读流 Readable

一、建立自定义可读流的类 MyRead

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

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 才会中止,不然会认为没有读取完成,会继续调用 _readnode

二、验证自定义可读流

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

实现一个自定义可写流 Writable

一、建立自定义可写流的类 MyWrite

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

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

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

二、验证自定义可写流

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

一、建立自定义可双工流的类 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 的功能,可是读和写互不影响,互不关联。post

二、验证自定义双工流

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

一、建立自定义可转化流的类 MyTransform

转化流的意思是便可以看成可读流,又能够看成可写流,建立一个类名为 MyTransform,并继承 stream 中的 Transform 类,重写 _transform 方法,该方法的参数和 _write 相同。ui

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 均可以使用。

二、验证自定义转化流

// 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来源:掘金著做权归做者全部。商业转载请联系做者得到受权,非商业转载请注明出处。

相关文章
相关标签/搜索