js读取http chunk流_极简 Node.js入门 教程双工流
点击上方蓝字关注我们
小编提示: 本文是由 ICBU 的谦行小哥哥出品,我们会持续发出极简 Node.js入门 教程,敬请期待哦,文中有比较多的演示代码建议横屏阅读
双工流就是同时实现了 Readable 和 Writable 的流,即可以作为上游生产数据,又可以作为下游消费数据,这样可以处于数据流动管道的中间部分,即
rs.pipe(rws1).pipe(rws2).pipe(rws3).pipe(ws);
在 NodeJS 中双工流常用的有两种
Duplex
Transform
实现Duplex
和 Readable、Writable 实现方法类似,实现 Duplex 流非常简单,但 Duplex 同时实现了 Readable 和 Writable, NodeJS 不支持多继承,所以我们需要继承 Duplex 类
继承 Duplex 类
实现 _read() 方法
实现 _write() 方法
相信看过前面章节后对 read()、write() 方法的实现不会陌生,和 Readable、Writable 完全一样
const Duplex = require('stream').Duplex;const myDuplex = new Duplex({ read(size) { // ... }, write(chunk, encoding, callback) { // ... }});
构造函数参数
Duplex 实例内同时包含可读流和可写流,在实例化 Duplex 类的时候可以传递几个参数
readableObjectMode : 可读流是否设置为 ObjectMode,默认 false
writableObjectMode : 可写流是否设置为 ObjectMode,默认 false
allowHalfOpen : 默认 true, 设置成 false 的话,当写入端结束的时,流会自动的结束读取端
小例子
了解了 Readable 和 Writable 之后看 Duplex 非常简单,直接用一个官网的例子
const Duplex = require('stream').Duplex;const kSource = Symbol('source');class MyDuplex extends Duplex { constructor(source, options) { super(options); this[kSource] = source; } _write(chunk, encoding, callback) { // The underlying source only deals with strings if (Buffer.isBuffer(chunk)) chunk = chunk.toString(); this[kSource].writeSomeData(chunk); callback(); } _read(size) { this[kSource].fetchSomeData(size, (data, encoding) => { this.push(Buffer.from(data, encoding)); }); }}
当然这是不能执行的伪代码,但是 Duplex 的作用可见一斑,进可以生产数据,又可以消费数据,所以才可以处于数据流动管道的中间环节,Node.js 中常见的 Duplex 流有
Tcp Scoket
Zlib
Crypto
Transform
Transform 同样是双工流,看起来和 Duplex 重复了,但两者有一个重要的区别:Duplex 虽然同事具备可读流和可写流,但两者是相对独立的;Transform 的可读流的数据会经过一定的处理过程自动进入可写流
虽然会从可读流进入可写流,但并不意味这两者的数据量相同,上面说的一定的处理逻辑会决定如果 tranform 可读流,然后放入可写流,transform 原义即为转变,很贴切的描述了 Transform 流作用
最常见的压缩、解压缩用的 zlib 即为 Transform 流,压缩、解压前后的数据量明显不同,儿流的作用就是输入一个 zip 包,输入一个解压文件或反过来。我们平时用的大部分双工流都是 Transform。
实现 Tranform
Tranform 类内部继承了 Duplex 并实现了 writable.write() 和 readable._read() 方法,自定义一个 Transform 流,只需要三个步骤
继承 Transform 类
实现 _transform() 方法
实现 _flush() 方法(可以不实现)
_transform(chunk, encoding, callback) 方法用来接收数据,并产生输出,参数我们已经很熟悉了,和 Writable 一样, chunk 默认是 Buffer,除非 decodeStrings 被设置为 false
在 _transform() 方法内部可以调用 this.push(data) 生产数据,交给可写流,也可以不调用,意味着输入不会产生输出
当数据处理完了必须调用 callback(err, data) ,第一个参数用于传递错误信息,第二个参数可以省略,如果被传入了,效果和 this.push(data) 一样
transform.prototype._transform = function (data, encoding, callback) { this.push(data); callback();};transform.prototype._transform = function (data, encoding, callback) { callback(null, data);};
有些时候,transform 操作可能需要在流的最后多写入可写流一些数据。例如, Zlib流会存储一些内部状态,以便优化压缩输出。在这种情况下,可以使用_flush()方法,它会在所有写入数据被消费、触发 'end'之前被调用
Transform 事件
Transform 流有两个常用的事件
来自 Writable 的 finish
来自 Readable 的 end
当调用 transform.end() 并且数据被 _transform() 处理完后会触发 finish,调用_flush后,所有的数据输出完毕,触发end事件
对比
了解了 Readable 和 Writable 之后,理解双工流十分自然,但两者的区别会让一些初学者困惑,简单的区分:Duplex 的可读流和可写流之间并没有直接关系,Transform 中可读流的数据会经过处理后自动放入可写流中。
看两个简单的例子就能直观了解到 Duplex 和 Transform 的区别
TCP socket
net 模块可以用来创建 socket,socket 在 NodeJS 中是一个典型的 Duplex,看一个 TCP 客户端的例子
var net = require('net');//创建客户端var client = net.connect({port: 1234}, function() { console.log('已连接到服务器'); client.write('Hi!');});//data事件监听。收到数据后,断开连接client.on('data', function(data) { console.log(data.toString()); client.end();});//end事件监听,断开连接时会被触发client.on('end', function() { console.log('已与服务器断开连接');});
可以看到 client 就是一个 Duplex,可写流用于向服务器发送消息,可读流用于接受服务器消息,两个流内的数据并没有直接的关系。
gulp
gulp 非常擅长处理代码本地构建流程,看一段官网的示例代码
function css() { return src('client/templates/*.less') .pipe(less()) .pipe(minifyCSS()) .pipe(dest('build/css'))}
其中 less() 和 minify() 就是典型的 Transform,处理流程大概是
.less 源码文件 -> less() -> css 文件 -> minify -> 压缩后的 css
可以看出来,less() 和 minify() 都是对输入数据做了些特殊处理,然后交给了输出数据。这样简单的对比就能看出 Duplex 和 Transform 的区别,在平时使用的时候,当一个流同时面向生产者和消费者服务的时候会选择 Duplex,当只是对数据读取后需要对之做一些转换工作的时候就会选择使用 Tranform
through2
日常数据处理 Transform 使用非常频繁,通过社区模块 through2 模块可以方便封装一个 Transform 流,API 十分简洁
through2([ options, ] [ transformFunction ] [, flushFunction ])
options 中
objectMode
设置为 true 后可以使用对象模式,也可以直接使用 through2.obj() 方法达到同样效果transformFunction:用于处理数据转换部分,有三个参数
chunk:当前处理的数据 Buffer
encoding:使用的编码
callback:
flushFunction:可选项,在流结束之前调用,可以用来处理一些没有完成或者需要收尾的工作
看个官网示例,实现功能 > 读取 ex.txt 内容,把字符 a 转成字符 z,输出到文件 out.txt 中
fs.createReadStream('ex.txt') .pipe(through2(function (chunk, encoding, callback) { for (var i = 0; i < chunk.length; i++) if (chunk[i] == 97) { chunk[i] = 122 // swap 'a' for 'z' } this.push(chunk); // 内容放到输出流,必须在 callback 之前调用,可以调用多次 callback(); // 最后不要忘记调用 })) .pipe(fs.createWriteStream('out.txt')) .on('finish', () => doSomethingSpecial());
了解了这五个章节的内容可以简单使用 Node.js 流了,处于理解成本只介绍了常用功能,全部功能可以阅读 Node.js Stream API
pipeline
const { pipeline } = require('stream');
pipeline 方法的作用类似于链式调用 pipe() 方法 ,在管道内传输多个流,在管道任务结束后提供回调
stream.pipeline(source[, ...transforms], destination, callback)
source:可读流
...tranforms:双工流
destination:可写流
callback:当管道完全地完成时调用
const { pipeline } = require('stream');const fs = require('fs');const zlib = require('zlib');pipeline( fs.createReadStream('archive.tar'), zlib.createGzip(), fs.createWriteStream('archive.tar.gz'), (err) => { if (err) { console.error('管道传送失败', err); } else { console.log('管道传送成功'); } });
写在最后
方凳雅集是由阿里巴巴B系6大BU(1688,ICBU,零售通,AE,企业金融,考拉)共同维护的公众号奥,我们会定期发送优质好文,欢迎扫码关注
求关注
求转发
js读取http chunk流_极简 Node.js入门 教程双工流相关推荐
- c语言5基础教程,[简001]《极简C语言入门教程》共5章
Saturday,May 18,2019 ---Andy ###目录: 前言 第一章 数据类型 1.1 数据类型 1.2 宏定义.常量.变量(一般和指针型) 第二章 格式化输入输出 2.1 输入 2. ...
- js 延迟几秒执行_深入研究 Node.js 的回调队列
队列是 Node.js 中用于有效处理异步操作的一项重要技术. 在本文中,我们将深入研究 Node.js 中的队列:它们是什么,它们如何工作(通过事件循环)以及它们的类型. Node.js 中的队列是 ...
- 极简 Node.js 入门 - 3.2 文件读取
Node.js 提供了多种读取文件的 API fs.readFile fs.readFile(path[, options], callback) 是最常用的读取文件方法,用于异步读取文件的全部内容 ...
- tensorflow源码编译教程_极简入门TensorFlow C++源码
前一段时间,一直在忙框架方面的工作,偶尔也会帮业务同学去优化优化使用TensorFlow的代码,也加上之前看了dmlc/relay,nnvm的代码,觉得蛮有意思,也想分别看下TensorFlow的Gr ...
- node.js使用手册_权威的Node.js手册
node.js使用手册 Note: you can get a PDF, ePub, or Mobi version of this handbook for easier reference, or ...
- node.js 模块_如何创建Node JS可重用模块
node.js 模块 In my previous post, we have discussed about "How to export and import a Node JS Mod ...
- Node.js (上)(超级详细的node.js学习笔记 !!!)
目录 一.初识Node.js与内置模块 1.之前知识回顾(为Node.js理解做铺垫) 1.1浏览器中的js的组成部分 1.2 为什么js可以在浏览器中被执行 1.3 为什么浏览器可以操作Bom和Do ...
- doodoo.js发布1.1.0 -- 中文最佳实践Node.js Web快速开发框架,支持Koa.js, Express.js中间件。包含多项功能改进,及Bug修复。...
2019独角兽企业重金招聘Python工程师标准>>> doodoo.js发布1.1.0 -- 中文最佳实践Node.js Web快速开发框架,支持Koa.js, Express.j ...
- js 转json_2020年了为啥 还要学 Node.js
前言 前些日子刷知乎看到个 2019 年初的问题 2019年nodejs凉了吗?凉到什么程度了?才看到问题的时候吃了一惊,是不是我在的公司大量使用 Node.js 让我有了幸存者偏差,前端社区已经沧海 ...
最新文章
- springMVC 前后台日期格式传值解决方式之一(共二) @DateTimeFormat的使用和配置...
- Core Dump解析(1)
- table单元格样式
- ELK + Filebeat日志分析系统安装
- 10. zf workflow
- 俄罗斯方块java分析_[源码和文档分享]基于Java的俄罗斯方块游戏
- Excel在数据分析和日常工作的运用
- 编译原理——将代码翻译成四元式序列
- 【程序员(媛)国人之光】知(美)识(色)贩卖贴】非标题党】
- 基因重组-冲刺日志(第七天)
- JAVA实现音频采样率转换
- DSP28335 ecap使用
- Linux企业应用——mysql(一)之mysql初始化、mysql与phpadmin、mysql主从复制
- NVMe Protect Information
- linux 耳机设备文件,linux耳机
- 百度地图画扇形区域覆盖(大小方向颜色透明图可调)
- 小黄图升级了,接入更加强大的鉴黄功能
- mysql 如何修改用户密码_如何更改MySQL用户密码
- 递归算法(二分查找)
- 英语文章关于计算机的,关于计算机的英语范文5篇
热门文章
- ZOJ-2008-Invitation Cards(dijkstra)
- javaWeb -- 虚拟主机以及虚拟目录映射的配置
- VS2008 在IE8中 调试 ActiveX控件 无法进入断点的解决方法 设置VS2008和IE8 调试ATL MFC ActiveX控件
- 速成pytorch学习——6天Dataset和DataLoader
- tensorflow出现报错AttributeError: module ‘tensorflow.python.keras.backend‘ has no attribute ‘get_graph‘
- HR面必知黑话!错过后悔!
- 超值赛题分享大礼包,你的“六一”礼物来咯!
- 【论文复现】使用fastText进行文本分类
- oracle ora-01476: 除数为 0,Oracle常见错误:ORA-01403 的根本原因和解决方案
- python tablewidget 颜色_更改QTableWidget的默认选择颜色,并使其半透明