按照官方的定义node
流(stream)是 Node.js 中处理流式数据的抽象接口。stream模块用于构建实现了流接口的对象。
咱们通常是直接使用node提供的流对象,例如在服务器请求、文件模块中使用。服务器
data事件在可读流将数据传给消费者后触发,特别注意的是,添加了该事件的流会自动切换为流动模式, end事件在当流中没有数据可供消费时触发:ui
const stream = fs.createReadStream('./file.txt') // 默认静止态 let chunks = [] stream.on("data", (chunk) => { // 变成流动态 chunks.push(chunk) }) stream.on("end", () => { constcontent = Buffer.concat(chunks).toString() console.log(content) })
readable事件代表流有新的动态:要么有新的数据,要么到达流的尽头。下面是读取文件的例子:code
const stream = fs.createReadStream('./file.txt') let chunks = [] stream.on("readable", () => { // stream中无数据也会触发readable, 此时read方法获得null console.log('触发readable'); let data; while (data = stream.read(1024)) { chunks.push(data) console.log('读取数据', data); } }) stream.on("end", () => { const content = Buffer.concat(chunks).toString(); console.log(content) })
使用readable会使流的状态变成静止态,即便监听了data事件。在调用read方法且有返回数据时会触发data事件。上面代码中,read方法读取内部缓冲中的数据,若是不指定size参数,则是读取内部缓冲中的全部数据,注意不是流中的全部数据,不指定size的话也就不必使用while循环了,直接一次性读取,while循环代码块可变为:server
data = stream.read() data && chunks.push(data) console.log('读取数据', data);
根据运行结果,read方法将缓冲区数据读完后会触发readable事件,也就是当read()返回null后触发。对象
定义见官方文档,下面例子使用pipe响应http请求接口
const http = require('http') const fs = require('fs') const server = http.createServer() server.on('request', (request, response) => { const stream = fs.createReadStream('./file.txt') stream.pipe(response) }) server.listen(8888)
数据流会被自动管理,因此即便可读流更快,目标可写流也不会超负荷。
上面的例子能够用data事件改写:事件
//.... server.on('request', (request, response) => { const stream = fs.createReadStream('./file.txt') stream.on("data", (chunk) => { response.write(chunk) }) stream.on("end", () => { response.end() // 使用pipe的话默认会在可读流触发end事件后调用end()结束写入 }) }) //...
另外pipe支持链式操做: a.pipe(b).pipe(c)
等价于 a.pipe(b); a.pipe(c)
ip
可读流流动态和静止态的切换,改变data事件是否触发文档
这两个事件是对于可写流的
若是可写流调用write() 返回 false,说明写的太快了,不能再往里面写了。当能够继续写入数据到流时会触发 'drain' 事件。
finish事件在调用end() 且缓冲数据都已传给底层系统以后触发。
上面的例子已有涉及到。write是写入数据到可写流,end代表写入完毕,之久不能再调用write了