Stream 流模块

操作系统采用数据块(chunk)的方式读取数据,每收到一次数据,就存入缓存。

Node应用程序有两种缓存的处理方式,第一种是等到所有数据接收完毕,一次性从缓存读取,这就是传统的读取文件的方式(遇上大文件很容易使内存爆仓)*;第二种是采用“数据流”的方式,收到一块数据,就读取一块,即在数据还没有接收完成时,就开始处理它(像流水一样)

基本流

可读流在创建时都是暂停模式,有暂停模式和流动模式,二者之间可以互相转换

管道流

管道提供了一个输出流到输入流的机制。通常用于从一个流中获取数据并将数据传递到另外一个流中>(把文件比作装水的桶,而水就是文件里的内容,用一根管子(pipe)连接两个桶使得水从一个桶流入另一个桶,这样就慢慢的实现了大文件的复制过程)

链式流

链式是通过连接输出流到另外一个流并创建多个对个流操作链的机制,看起有点像分水器。
下面示例用管道和链式来压缩文件 创建 compress.js 文件

const fs = require("fs");
const zlib = require('zlib')
// 压缩 README.md 文件为 README.md.gz
fs.createReadStream('./README.md')
  .pipe(zlib.createGzip())
  .pipe(fs.createWriteStream('README.md.gz'))
console.log("文件压缩完成")

Node事件

所有的流Stream 对象都是 EventEmitter的实例

  • data - 当有数据可读时触发。
  • end - 没有更多的数据可读时触发。
  • error - 在接收和写入过程中发生错误时触发。
  • finish - 所有数据已被写入到底层系统时触发。

流复制

示例演示带进度条显示

const fs = require('fs')
const out = process.stdout

let paths = {
    src: '../test.mp4',
    dist: '../test1.mp4'
}

function copy(paths){
    let {src, dist} = paths
    let readStream = fs.createReadStream(src)
    let writeStream = fs.createWriteStream(dist)

    let stat = fs.statSync(src),
        totalSize = stat.size,
        progress = 0,
        lastSize = 0,
        startTime = Date.now()

    readStream.on('data', function(chunk) {
        progress += chunk.length;
    })

    // 添加了一个递归的setTimeout来做一个旁观者
    // 每500ms观察一次完成进度,并把已完成的大小、百分比和复制速度一并写到控制台上
    // 当复制完成时,计算总的耗费时间
    setTimeout(function show() {
        let percent = Math.ceil((progress / totalSize) * 100)
        let size = Math.ceil(progress / 1000000)
        let diff = size - lastSize
        lastSize = size
        out.clearLine()
        out.cursorTo(0)
        out.write(`已完成${size}MB,${percent}%, 速度:${diff * 2}MB/s`)
        if (progress < totalSize) {
            setTimeout(show, 500)
        } else {
            let endTime = Date.now()
            console.log(`共用时:${(endTime - startTime) / 1000}秒。`)
        }
    }, 500)
}
copy(paths)

应用场景

流除了用来处理文件复制。当然还可以用它来处理。
HTTP requests, on the clientHTTP responses, on the server、 fs write streamszlib streamscrypto streamsTCP sockets、 child process stdin、 process.stdout, process.stderr

本作品采用《CC 协议》,转载必须注明作者和本文链接
pardon110
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!
开发者 @ 社科大
文章
134
粉丝
24
喜欢
101
收藏
55
排名:106
访问:8.9 万
私信
所有博文
社区赞助商