什么是流?
- 是一种 以高效的方式处理读 / 写文件、网络通信 或任何类型的端到端的信息交换。当告诉程序读取文件时,它可以 逐个片段 的读取并处理(而无需全部保存到内存中)
- Node.js 的 stream 模块 提供了构建所有流 API 的基础。 所有的流都是 EventEmitter 的实例。
内存效率: 无需加载大量数据到内存即可处理。
时间效率: 当获得数据之后可立即开始处,而不必等到整个数据 有效负载才开始。
示例: 从磁盘读取文件
const http = require('http')
const fs = require('fs')
const server = http.createServer((req, res) => {
const stream = fs.createReadStream(__dirname + '/data.txt')
stream.pipe(res) // 将数据块流式传入http客户端(获取来源流,并将其通过管道传输到目标流。)
})
server.listen(3000)
链式调用: pipe() 方法的返回值是目标流,这是非常方便的事情,它使得可以链接多个 pipe() 调用
src.pipe(dest1).pipe(dest2)
流驱动的 Node.js API
流的分类
- Readable: 可以通过管道读取、但不能通过管道写入的流(可以接收数据,但不能向其发送数据)。 当推送数据到可读流中时,会对其进行缓冲,直到使用者开始读取数据为止。
- Writable: 可以通过管道写入、但不能通过管道读取的流(可以发送数据,但不能从中接收数据)。
- Duplex: 可以通过管道写入和读取的流,基本上相对于是可读流和可写流的组合。
- Transform: 类似于双工流、但其输出是其输入的转换的转换流。
创建流
// 首先创建流对象
const Stream = require('stream')
const readableStream = new Stream.Readable()
// 然后实现_read
readableStream._read = () => {}
// 也可以使用read选项实现_read
const readableStream = new Stream.Readable({
read() {}
})
//现在,流已经初始化流,可以向其发送数据流。
readableStream.push('hi!')
readableStream.push('ho!')
从可读流中获取数据
- 方法一: 使用可写流
const Stream = require('stream')
const readableStream = new Stream.Readable({
read() {}
})
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())
})
发送数据到可写流
writableStream.write('hey!\n')
使用信号通知已结束写入的可写流
const Stream = require('stream')
const readableStream = new Stream.Readable({
read() {}
})
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() // --------------------------这句