有用的内置Node.js APIs( 四 )

  • 可写:写入到文件、HTTP响应、TCP套接字、标准输出等 。
  • 双工:既可读又可写的流 。
  • 转换:转换数据的双工流 。
  • 每块数据都以Buffer对象的形式返回,它代表一个固定长度的字节序列 。你可能需要将其转换为字符串或其他适当的类型进行处理 。
    该示例代码有一个filestream项目,它使用一个转换流来解决filecompress项目中的文件大小问题 。和以前一样,它在声明一个继承TransformCompress类之前,接受并验证了输入和输出的文件名:
    import { createReadStream, createWriteStream } from 'fs';import { Transform } from 'stream';// compression Transformclass Compress extends Transform {constructor(opts) {super(opts);this.chunks = 0;this.lengthOrig = 0;this.lengthNew = 0;}_transform(chunk, encoding, callback) {constdata = https://www.huyubaike.com/biancheng/chunk.toString(),// buffer to stringcontent = data.replace(/n/s+/g,'\n')// trim leading spaces.replace(/\/\/.*?\n/g, '')// remove // comments.replace(/\s+/g, ' ')// remove whitespace.replace(/\/\*.*?\*\//g, '')// remove /* comments */.replace(/<!--.*?-->/g, '')// remove <!-- comments -->.replace(/\s*([<>(){}}[\]])\s*/g, '$1') // remove bracket spaces.trim();this.chunks++;this.lengthOrig += data.length;this.lengthNew += content.length;this.push( content );callback();}}当一个新的数据块准备好时,_transform方法被调用 。它以Buffer对象的形式被接收,并被转换为字符串,被最小化,并使用push()方法输出 。一旦数据块处理完成,一个callback()函数就会被调用 。
    应用程序启动了文件读写流,并实例化了一个新的compress对象:
    // process streamconstreadStream = createReadStream(input),wr// process streamconstreadStream = createReadStream(input),writeStream = createWriteStream(output),compress = new Compress();console.log(`processing ${ input }`)传入的文件读取流定义了.pipe()方法,这些方法通过一系列可能(或可能不)改变内容的函数将传入的数据输入 。在输出到可写文件之前,数据通过compress转换进行管道输送 。一旦流结束,最终on('finish')事件处理函数就会执行:
    readStream.pipe(compress).pipe(writeStream).on('finish', () => {console.log(`file size${ compress.lengthOrig }`);console.log(`output${ output }`);console.log(`chunksreadStream.pipe(compress).pipe(writeStream).on('finish', () => {console.log(`file size${ compress.lengthOrig }`);console.log(`output${ output }`);console.log(`chunks${ compress.chunks }`);console.log(`file size${ compress.lengthNew } - saved ${ Math.round((compress.lengthOrig - compress.lengthNew) / compress.lengthOrig * 100) }%`);});使用任意大小的HTML文件的例子运行项目代码:
    node filestream.js ./test/example.html ./test/output.html
    有用的内置Node.js APIs

    文章插图
    这是对Node.js流的一个小例子 。流处理是一个复杂的话题 , 你可能不经常使用它们 。在某些情况下,像Express这样的模块在引擎盖下使用流 , 但对你的复杂性进行了抽象 。
    你还应该注意到数据分块的挑战 。一个块可以是任何大小 , 并以不便的方式分割传入的数据 。考虑对这段代码最小化:
    <script type="module">// example scriptconsole.log('loaded');</script>两个数据块可以依次到达:
    <script type="module">// example以及:
    <script>console.log('loaded');</script>独立处理每个块的结果是以下无效的最小化脚本:
    <script type="module">script console.log('loaded');</script>解决办法是预先解析每个块,并将其分割成可以处理的整个部分 。在某些情况下,块(或块的一部分)将被添加到下一个块的开始 。
    尽管会出现额外的复杂情况,但是最好将最小化应用于整行 。因为<!-- -->/* */注释可以跨越不止一行 。下面是每个传入块的可能算法:
    1. 将先前块中保存的任何数据追加到新块的开头 。
    2. 从数据块中移除任意整个<!-- 到 --> 以及 /* 到 */部分 。
    3. 将剩余块分为两部分 。其中part2以发现的第一个<!--/*开始 。如果两者都存在,则从part2中删除除该符号以外的其他内容 。如果两者都没有找到,则在最后一个回车符处进行分割 。如果没有找到,将

      推荐阅读