在Node.js中创建双工流

1,172 阅读4分钟

双联流是Node.js中流的一个基本类别。然而,它们经常被误解,包括Duplex流。

这种类型的流是混合型的,这意味着它在实现时期望有一个readwrite 方法。

在这篇文章中,我们将回顾Duplex流以及如何创建一个流。但在此之前,让我们回顾一下什么是流。

在这篇文章中,对JavaScript和Node.js的了解会有帮助,但这不是必须的。

什么是流?

流是指从一个源头收集的数据,并以一个序列带到另一个地方。在线流媒体视频就是一个例子:虽然视频内容以一个序列传递给你,但完整的内容还没有出现。

流媒体被分为四类。可写流、可读流、双工流和转换流。

可读流从文件或源读取数据,并将其传递给主应用程序。然后,一个缓冲区存储数据,以备将数据传递给应用程序时出现延迟。

当可写流时,其功能正好相反。数据从应用程序中读到文件中。如果数据传输变慢,也有一个缓冲区,然后将其存储在那里。

另一方面,Duplex流是可读流和可写流的混合体,这两种流是相互独立的。

变换流也像双工流,但可读流和可写流都是连接的。

这种连接使应用程序能够写入数据,但在那里,数据必须在传递到可读流之前进行处理。

双工流的例子

就像我们前面解释的那样,双工流基本上是可读流和可写流的混合物。

双工流的一个例子是Socket,它提供两个通道来发送和接收数据。

双工流的其他例子有。

创建一个自定义的双工流来延迟块状数据

要在Node.js中创建一个Duplex流,开始从流模块中导入所需的方法。

const { PassThrough } = require('stream')
const tunnel = new PassThrough()

PassThrough 流是一个基本类型的双工流,它作为一个隧道,将我们的可读流输送到可写流。

所以,有了这个隧道,我们就可以检查到可写流的数据处理。

接下来,让我们使用可读流读取一个文件,并使用writeStream ,将其写入可写流中。

const { PassThrough } = require("stream");
const { createReadStream, createWriteStream } = require("fs"); 
const readStream = createReadStream("./README.md"); // read data from this file
const writeStream = createWriteStream("./copy.txt"); // write data to this file

接下来,我们可以检查缓冲区中的内容,看看数据是否在隧道中通过。

const { PassThrough } = require("stream");
const { createReadStream, createWriteStream } = require("fs");
const readStream = createReadStream("./README.md");
const writeStream = createWriteStream("./copy.txt");

const tunnel = new PassThrough();

tunnel.on("data", (chunk) => {
  console.log("bytes:", chunk); // bytes: <Buffer 23 20 4a 61 76 61 53 63 72 69 70 74 20 41 6c 67 6f 72 69 74 68 6d 73 20 61 6e 64 20 44 61 74 61 20 53 74 72 75 63 74 75 72 65 73 0a 0a 54 68 69 73 20 ... 1767 more bytes>
});

readStream.pipe(tunnel).pipe(writeStream);

除了PassThrough ,我们还有Throttle 来延迟数据在管道中从一个源头到另一个源头的传递时间。我们可以使用Duplex流来设置数据进入我们的应用程序时的延迟。

const { PassThrough, Duplex } = require("stream");
const { createReadStream, createWriteStream } = require("fs");
const readStream = createReadStream("./movie.mp4");
const writeStream = createWriteStream("./copy.mp4");

class Throttle extends Duplex {
  /*
   * Class constructor will receive the injections as parameters.
   */
  constructor(time) {
    super();
    this.delay = time;
  }
  _read() {}

  // Writes the data, push and set the delay/timeout
  _write(chunk, encoding, callback) {
    this.push(chunk);
    setTimeout(callback, this.delay);
  }

  // When all the data is done passing, it stops.
  _final() {
    this.push(null);
  }
}

const tunnel = new PassThrough();
const throttle = new Throttle(500);

let amount = 0;
tunnel.on("data", (chunk) => {
  amount += chunk.length;
  console.log("bytes:", amount);
});

readStream.pipe(throttle).pipe(tunnel).pipe(writeStream);

通过上面的代码,我们创建了一个双工流,为我们的管道数据创建throttle(delay) 。这设置了一个500毫秒的延迟,Throttle 类中的方法推送了这个块。

_final() 方法只在数据传输完成后推送null。

我们还修改了我们的PassThrough 流,以增加它所读取的每个块的长度。

这就是响应在终端中以500毫秒的增量呈现的情况。

Response Renders In Terminal At 500 Millisecond Increments

结论

通过在Node.js中使用双工流,我们看到了如何将数据从一个流延迟到另一个流。

双工流在我们的数字世界中是相当重要的,而且大部分时间都在不知不觉中被使用,特别是在Socket中。这些都是强大的功能,因为它们是如何同时实现可读流和可写流的。

The postCreating Duplex streams in Node.jsappeared first onLogRocket Blog.