Node.js流的基础

Node.js是异步的,并且本质上是事件驱动的。 因此,它非常适合处理I / O绑定的任务。 如果您正在执行I / O操作的应用程序,则可以利用Node.js中可用的流。 因此,让我们详细研究Streams并了解它们如何简化I / O。

什么是流

流是unix管道,可让您轻松地从源读取数据并将其通过管道传输到目标。 简而言之,流不过是EventEmitter并实现了一些特殊方法。 根据实现的方法,流将变为可读,可写或双工(可读和可写)。 可读流可让您从源读取数据,而可写流可让您将数据写入目标。

如果您已经使用过Node.js,则可能遇到过流。 例如,在基于Node.js的HTTP服务器中, request是可读流, response是可写流。 您可能使用过fs模块,该模块可让您使用可读和可写文件流。

现在您已经了解了基础知识,让我们了解不同类型的流。 在本文中,我们将讨论可读和可写的流。 双工流不在本文讨论范围之内。

可读流

可读流使您可以从源中读取数据。 来源可以是任何东西。 它可以是文件系统上的简单文件,也可以是内存中的缓冲区,甚至可以是另一个流。 由于流是EventEmitters ,因此它们在各个点发出多个事件。 我们将使用这些事件来处理流。

从流阅读

从流中读取数据的最佳方法是侦听data事件并附加回调。 当有大量数据可用时,可读流将发出一个data事件,并执行您的回调。 看一下以下代码片段:

var fs = require('fs');
var readableStream = fs.createReadStream('file.txt');
var data = '';

readableStream.on('data', function(chunk) {
    data+=chunk;
});

readableStream.on('end', function() {
    console.log(data);
});

函数调用fs.createReadStream()为您提供可读的流。 最初,流处于静态状态。 一旦您侦听data事件并附加了回调,它就会开始流动。 之后,将读取大块数据并将其传递给您的回调。 流实现者决定data事件的频率。 例如,一旦读取了几KB数据,HTTP请求就可能发出data事件。 当您从文件中读取数据时,一旦读取一行,您可能会决定发出data事件。

当没有更多数据要读取(到达结束)时,流将发出end事件。 在以上代码段中,我们监听此事件以在结束时得到通知。

还有另一种从流中读取的方法。 您只需要在流实例上重复调用read() ,直到read()完所有数据块。

var fs = require('fs');
var readableStream = fs.createReadStream('file.txt');
var data = '';
var chunk;

readableStream.on('readable', function() {
    while ((chunk=readableStream.read()) != null) {
        data += chunk;
    }
});

readableStream.on('end', function() {
    console.log(data)
});

read()函数从内部缓冲区读取一些数据并返回。 当没有内容可读取时,它返回null 。 因此,在while循环中,我们检查是否为null并终止循环。 请注意,当可以从流中读取大量数据时,将发出readable事件。

设定编码

默认情况下,您从流中读取的数据是Buffer对象。 如果您正在阅读字符串,则可能不适合您。 因此,您可以通过调用Readable.setEncoding()在流上设置编码,如下所示。

var fs = require('fs');
var readableStream = fs.createReadStream('file.txt');
var data = '';

readableStream.setEncoding('utf8');

readableStream.on('data', function(chunk) {
    data+=chunk;
});

readableStream.on('end', function() {
    console.log(data);
});

在以上代码段中,我们将编码设置为utf8 。 结果,数据被解释为utf8并以字符串形式传递给您的回调。

管道

管道是一种很好的机制,您可以从源中读取数据并将其写入目标,而无需自己管理流程。 看一下以下代码片段:

var fs = require('fs');
var readableStream = fs.createReadStream('file1.txt');
var writableStream = fs.createWriteStream('file2.txt');

readableStream.pipe(writableStream);

上面的代码片段利用了pipe()函数将file1的内容写入file2 。 由于pipe()为您管理数据流,因此您不必担心数据流慢或快。 这使pipe()成为读取和写入数据的简洁工具。 您还应该注意, pipe()返回目标流。 因此,您可以轻松地利用此功能将多个流链接在一起。 让我们看看如何!

链式

假设您有一个存档,并想对其进行解压缩。 有多种方法可以实现此目的。 但是最简单,最干净的方法是使用管道和链接。 请看以下片段:

var fs = require('fs');
var zlib = require('zlib');

fs.createReadStream('input.txt.gz')
  .pipe(zlib.createGunzip())
  .pipe(fs.createWriteStream('output.txt'));

首先,我们从input.txt.gz文件创建一个简单的可读流。 接下来,我们将此流通过管道zlib.createGunzip()到另一个流zlib.createGunzip()zlib.createGunzip()内容。 最后,由于可以链接流,因此我们添加了可写流,以便将未压缩的内容写入文件。

附加方法

我们讨论了可读流中的一些重要概念。 这是您需要了解的更多流方法:

  1. Readable.pause() –此方法暂停流。 如果流已经在流动,它将不再发出data事件。 数据将保存在缓冲区中。 如果在静态(非流动)流上调用此流,则该流开始流动,但不会发出data事件。
  2. Readable.resume() –恢复暂停的流。
  3. readable.unpipe() –这将从管道目标中删除目标流。 如果传递了参数,它将停止将可读流传递到特定目标流中。 否则,将删除所有目标流。

可写流

可写流使您可以将数据写入目标。 像可读流一样,它们也是EventEmitters并在各个点发出各种事件。 让我们看看可写流中可用的各种方法和事件。

写入流

要将数据写入可写流,您需要在流实例上调用write() 。 以下代码段演示了此技术。

var fs = require('fs');
var readableStream = fs.createReadStream('file1.txt');
var writableStream = fs.createWriteStream('file2.txt');

readableStream.setEncoding('utf8');

readableStream.on('data', function(chunk) {
    writableStream.write(chunk);
});

上面的代码很简单。 它仅从输入流中读取数据块,然后使用write()写入目标。 该函数返回一个布尔值,指示操作是否成功。 如果为true ,则写入成功,您可以继续写入更多数据。 如果返回false ,则表示出了点问题,您目前无法编写任何内容。 可写流将通过发出drain事件来通知您何时可以开始写入更多数据。

数据结束

当您没有更多数据要写入时,您只需调用end()即可通知流您已完成写入。 假设res是HTTP响应对象,则通常需要执行以下操作将响应发送到浏览器:

res.write('Some Data!!');
res.end('Ended.');

当调用end()且已刷新所有数据块时,流将发出finish事件。 请注意,调用end()后无法写入流。 例如,以下内容将导致错误。

res.write('Some Data!!');
res.end();
res.write('Trying to write again'); //Error!

以下是与可写流相关的一些重要events

  1. error –表示在写/配管时发生了错误。
  2. pipe –将可读流传输到可写流中时,可写流会发出此事件。
  3. unpipe –在可读流上调用unpipe并停止将其输送到目标流中时发出。

结论

这就是所有关于流的基础知识。 流,管道和链接是Node.js的核心和最强大的功能。 如果负责任地使用,流确实可以帮助您编写简洁而高效的代码来执行I / O。

你喜欢这篇文章吗? 通过评论让我们知道您的想法。

From: https://www.sitepoint.com/basics-node-js-streams/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值