浅谈Nodejs中的​双工流

浅谈Nodejs中的​双工流

相关推荐:《node js教程》

双工流就是同时实现了 Readable 和 Writable 的流,即可以作为上游生产数据,又可以作为下游消费数据,这样可以处于数据流动管道的中间部分,即

 rs.pipe(rws1).pipe(rws2).pipe(rws3).pipe(ws);

登录后复制

在 NodeJS 中双工流常用的有两种

Duplex

Transform

Duplex

实现 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,默认 falsewritableObjectMode: 可写流是否设置为 ObjectMode,默认 falseallowHalfOpen: 默认 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 的作用可见一斑,进可以生产数据,又可以消费数据,所以才可以处于数据流动管道的中间环节,常见的 Duplex 流有

Tcp ScoketZlibCrypto

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 非常擅长处理代码本地构建流程,看一段官网的示例代码

gulp.src('client/templates/*.jade')  .pipe(jade())  .pipe(minify())  .pipe(gulp.dest('build/minified_templates'));

登录后复制

其中 jada() 和 minify() 就是典型的 Transform,处理流程大概是

.jade 模板文件 -> jada() -> html 文件 -> minify -> 压缩后的 html

登录后复制

可以看出来,jade() 和 minify() 都是对输入数据做了些特殊处理,然后交给了输出数据。

这样简单的对比就能看出 Duplex 和 Transform 的区别,在平时实用的时候,当一个流同事面向生产者和消费者服务的时候我们会选择 Duplex,当只是对数据做一些转换工作的时候我们便会选择使用 Tranform。

更多编程相关知识,请访问:node js教程!!

以上就是浅谈Nodejs中的​双工流的详细内容,更多请关注【创想鸟】其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2722817.html

(0)
上一篇 2025年3月7日 22:58:31
下一篇 2025年2月28日 03:15:20

AD推荐 黄金广告位招租... 更多推荐

相关推荐

  • 如何使用Llama Logs显示和调试NodeJS错误?

    本篇文章给大家介绍一下node开发神器–llama logs,使用llama logs实时可视化node错误。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。 相关推荐:《nodejs 教程》 你是否想知道程序内…

    2025年3月7日
    200
  • 使用Node.js+Vue.js来构建文件压缩应用程序

    相关推荐:《node js教程》 Node.js为我们提供了一个模块来协助文件压缩。在本文中,我们将构建一个应用程序,用户可以在该应用程序中上传他们想要压缩的文件,然后使用Node.js Zlib模块下载该文件的压缩版本。 前提 要继续学习…

    2025年3月7日 编程技术
    200
  • 23个需要了解的十分有用的nodejs库(推荐)

    相关推荐:《node js教程》 作为专业的开发人员,我们必须不断更新最新和最好的库,因为知道好的库,那么开发过程就可以依赖于它们,这会节省我们很多时间也有助于构建高质量的软件。 下面列表常见且好用的 NodeJS 库,反正我自己是已经收藏…

    2025年3月7日 编程技术
    200
  • 详解Node.js中的事件

    相关推荐:《nodejs 教程》 前端对事件肯定不陌生,为 window 绑定 scroll 事件 window.addEventListener(‘scroll’, ev => {console.log(ev);}); 登录后复制 …

    2025年3月7日
    200
  • 了解Node.js中的process对象

    相关推荐:《node js教程》 process 对象是一个全局变量,是一个 EventEmitter 实例,提供了当前 Node.js 进程的信息和操作方法 系统信息 process 对象提供了属性用于返回关键系统信息,常用的有 titl…

    2025年3月7日
    200
  • 提示Node应用性能的5个技巧

    相关推荐:《node js教程》 “如果你的 node 服务器前面没有 nginx, 那么你可能做错了。”— Bryan Hughes Node.js 是使用 最流行的语言— JavaScript 构建服务器端应用的领先工具 。由于可以同时…

    2025年3月7日
    200
  • 了解Node.js中的定时器

    相关推荐:《node js教程》 timer 用于安排函数在未来某个时间点被调用,Node.js 中的定时器函数实现了与 Web 浏览器提供的定时器 API 类似的 API,但是使用了事件循环实现,Node.js 中有四个相关的方法 set…

    2025年3月7日
    200
  • 谈谈Node.js中的文件写入

    本篇文章给大家介绍一下node.js中的文件写入。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。 相关推荐:《node js教程》 看完文件读取再看文件写入非常简单,两者的操作几乎一一对应 fs.writeFile fs.…

    2025年3月7日
    200
  • 了解nodejs中的事件和事件循环

    相关推荐:《nodejs 教程》 熟悉javascript的朋友应该都使用过事件,比如鼠标的移动,鼠标的点击,键盘的输入等等。我们在javascript中监听这些事件,从而触发相应的处理。 同样的nodejs中也有事件,并且还有一个专门的e…

    2025年3月7日
    200
  • 浅谈node连接mysql数据库的方法

    本篇文章和大家聊聊node连接mysql数据库的方法。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。 相关推荐:《node js教程》 node使用原生方式,连接mysql数据库 (async () => { // …

    2025年3月7日
    200

发表回复

登录后才能评论