Node.js流

了解流的含义,为何如此重要以及如何使用它们。

什么是流

流是支持Node.js应用程序的基本概念之一。

它们是一种有效处理读/写文件,网络通信或任何类型的端到端信息交换的方式。

流不是Node.js特有的概念。它们是几十年前在Unix操作系统中引入的,程序可以相互交互,使流通过管道运算符(|)。

例如,以传统方式,当您告诉程序读取文件时,会将文件从头到尾读入内存,然后进行处理。

通过使用流,您可以逐段读取它,在不将其全部保存在内存中的情况下处理其内容。

Node.jsstream模块提供了构建所有流API的基础。

为什么流

使用其他数据处理方法,流基本上提供了两个主要优点:

  • 记忆效率:您无需先将大量数据加载到内存中就可以对其进行处理
  • 时间效率:一开始就花更少的时间开始处理数据,而不是等到整个数据有效负载都可以开始时才开始处理数据

流的一个例子

一个典型的例子是从磁盘读取文件的例子。

使用节点fs模块,您可以读取文件,并在与http服务器建立新连接时通过HTTP提供文件:

const http = require('http')
const fs = require('fs')

const server = http.createServer(function (req, res) { fs.readFile(__dirname + ‘/data.txt’, (err, data) => { res.end(data) }) }) server.listen(3000)

readFile()读取文件的全部内容,并在完成后调用回调函数。

res.end(data)在回调中会将文件内容返回给HTTP客户端。

如果文件很大,则该操作将花费大量时间。这是使用流编写的相同内容:

const http = require('http')
const fs = require('fs')

const server = http.createServer((req, res) => { const stream = fs.createReadStream(__dirname + ‘/data.txt’) stream.pipe(res) }) server.listen(3000)

我们没有等待直到文件被完全读取,而是在准备好要发送的大量数据后立即开始将其流式传输到HTTP客户端。

管道()

上面的示例使用该行stream.pipe(res): 这pipe()在文件流上调用方法。

该代码的作用是什么?它获取源,并将其通过管道传输到目标。

您在源流上调用它,因此在这种情况下,文件流通过管道传递到HTTP响应。

的返回值pipe()方法是目标流,这是非常方便的事情,它使我们可以链接多个pipe()呼叫,如下所示:

src.pipe(dest1).pipe(dest2)

此构造与执行相同

src.pipe(dest1)
dest1.pipe(dest2)

流驱动的节点API

由于它们的优点,许多Node.js核心模块提供了本机流处理功能,最值得注意的是:

  • process.stdin返回连接到标准输入的流
  • process.stdout返回连接到stdout的流
  • process.stderr返回连接到stderr的流
  • fs.createReadStream()创建一个可读的文件流
  • fs.createWriteStream()创建一个可写的文件流
  • net.connect()启动基于流的连接
  • http.request()返回http.ClientRequest类的实例,该实例是可写流
  • zlib.createGzip()使用gzip(一种压缩算法)将数据压缩到流中
  • zlib.createGunzip()解压缩gzip流。
  • zlib.createDeflate()使用deflate(压缩算法)将数据压缩到流中
  • zlib.createInflate()解压缩放气流

不同类型的流

流分为四类:

  • Readable:您可以通过管道传输而不是通过管道传输的流(您可以接收数据,但不能向其发送数据)。当您将数据推送到可读流中时,将对其进行缓冲,直到使用者开始读取数据为止。
  • Writable:您可以通过管道传输而不是从管道传输的流(您可以发送数据,但不能从中接收数据)
  • Duplex:您可以同时通过管道传输和传输的流,基本上是可读流和可写流的组合
  • Transform:转换流类似于双工,但输出是其输入的转换

如何创建可读流

我们从stream模块,然后我们对其进行初始化

const Stream = require('stream')
const readableStream = new Stream.Readable()

现在,流已初始化,我们可以向其发送数据了:

readableStream.push('hi!')
readableStream.push('ho!')

如何创建可写流

为了创建可写流,我们扩展了基础Writable对象,并实现其_write()方法。

首先创建一个流对象:

const Stream = require('stream')
const writableStream = new Stream.Writable()

然后实施_write

writableStream._write = (chunk, encoding, next) => {
    console.log(chunk.toString())
    next()
}

现在,您可以通过以下方式传递可读流:

process.stdin.pipe(writableStream)

如何从可读流中获取数据

我们如何从可读流中读取数据?使用可写流:

const Stream = require('stream')

const readableStream = new Stream.Readable() const writableStream = new Stream.Writable()

writableStream._write = (chunk, encoding, next) => { console.log(chunk.toString()) next() }

readableStream.pipe(writableStream)

readableStream.push(‘hi!’) readableStream.push(‘ho!’)

您还可以使用readable事件:

readableStream.on('readable', () => {
  console.log(readableStream.read())
})

如何将数据发送到可写流

使用流write()方法:

writableStream.write('hey!\n')

用信号通知您已结束编写的可写流

使用end()方法:

const Stream = require('stream')

const readableStream = new Stream.Readable() const writableStream = new Stream.Writable()

writableStream._write = (chunk, encoding, next) => { console.log(chunk.toString()) next() }

readableStream.pipe(writableStream)

readableStream.push(‘hi!’) readableStream.push(‘ho!’)

writableStream.end()

免费下载我的Node.js手册


更多节点教程: