zoukankan      html  css  js  c++  java
  • NodeJS —— 自定义流的实现

    概述

    常见的自定义流有四种,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
    来源:掘金
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • 相关阅读:
    我不会用 Triton 系列:Model Warmup 的使用
    我不会用 Triton 系列:Python Backend 的使用
    C++11 Memory Order
    我不会用 Triton 系列:Triton 搭建 ensemble 过程记录
    我不会用 Triton 系列:Stateful Model 学习笔记
    CUDA 概念汇总
    字符串的扩展
    梦学谷会员管理系统
    普希金-假如生活欺骗了你
    变量的解构赋值
  • 原文地址:https://www.cnblogs.com/jebysun/p/9400002.html
Copyright © 2011-2022 走看看