What's the proper way to handle back-pressure in a node.js Transform stream?

前端 未结 6 654
天命终不由人
天命终不由人 2020-12-25 13:55

Intro

These are my first adventures in writing node.js server side. It\'s been fun so far but I\'m having some difficulty understanding the proper way to implement

6条回答
  •  爱一瞬间的悲伤
    2020-12-25 14:41

    I think Transform is suitable for this, but I would perform the inflate as a separate step in the pipeline.

    Here's a quick and largely untested example:

    var zlib        = require('zlib');
    var stream      = require('stream');
    var transformer = new stream.Transform();
    
    // Properties used to keep internal state of transformer.
    transformer._buffers    = [];
    transformer._inputSize  = 0;
    transformer._targetSize = 1024 * 38;
    
    // Dump one 'output packet'
    transformer._dump       = function(done) {
      // concatenate buffers and convert to binary string
      var buffer = Buffer.concat(this._buffers).toString('binary');
    
      // Take first 1024 packets.
      var packetBuffer = buffer.substring(0, this._targetSize);
    
      // Keep the rest and reset counter.
      this._buffers   = [ new Buffer(buffer.substring(this._targetSize)) ];
      this._inputSize = this._buffers[0].length;
    
      // output header
      this.push('HELLO WORLD');
    
      // output compressed packet buffer
      zlib.deflate(packetBuffer, function(err, compressed) {
        // TODO: handle `err`
        this.push(compressed);
        if (done) {
          done();
        }
      }.bind(this));
    };
    
    // Main transformer logic: buffer chunks and dump them once the
    // target size has been met.
    transformer._transform  = function(chunk, encoding, done) {
      this._buffers.push(chunk);
      this._inputSize += chunk.length;
    
      if (this._inputSize >= this._targetSize) {
        this._dump(done);
      } else {
        done();
      }
    };
    
    // Flush any remaining buffers.
    transformer._flush = function() {
      this._dump();
    };
    
    // Example:
    var fs = require('fs');
    fs.createReadStream('depth_1000000')
      .pipe(zlib.createInflate())
      .pipe(transformer)
      .pipe(fs.createWriteStream('depth_1000000.out'));
    

提交回复
热议问题