How to pause nodejs flowing stream when destination is full

1.2k views Asked by At
$ node --version
v0.10.29

Similar to "Cannot switch to old mode now" - Node.JS apn module error in tls.connect function I'm getting a "Cannot switch to old mode now" error thrown when pausing a readable stream (in this case a HTTP response/IncomingMessage)

_stream_readable.js:732
    throw new Error('Cannot switch to old mode now.');
          ^
Error: Cannot switch to old mode now.
    at emitDataEvents (_stream_readable.js:732:11)
    at IncomingMessage.Readable.pause (_stream_readable.js:723:3)

The IncomingMessage has XML in the body which I'm piping in to a sax-js handler. The handler then writes output to a PassThrough stream which is piped to some destination. Reading the docs on readable.pause() and readable.resume() I'm not sure what I'm doing wrong. Is there something about flowing streams that I'm missing, or am I implementing the wrong pattern below?

function wrapStream(incoming) {
  var dest = new PassThrough();
  dest.setEncoding("utf8");

  dest.on("drain", function () {
    incoming.resume();
  });

  var saxStream = sax.createStream(true, {});

  saxStream.print = function() {
    var args = Array.prototype.slice.apply(arguments);

    /*
     * It's my understanding that if the dest stream is full,
     * we should pause the IncomingMessage
     * until the dest drains.
     */
    if (!dest.write.apply(dest, args)) {
      // throws error here.
      incoming.pause();
    }
  };

  /*
   * Attach handlers to saxStream here.
   * They use the print() function to write data to dest.
   */

  saxStream.on("end", function() {
    dest.end();
  });

  incoming.pipe(saxStream);

  return dest;
}

var output = fs.createWriteStream("/tmp/test.xml");

http.get(url, function(res) {
  var saxStream = wrapStream(res);

  saxStream.pipe(output);
});
1

There are 1 answers

0
nfroidure On BEST ANSWER

Streams embed a mechanism named back pressure. Piping a stream to another automatically take care of when the destination stream is busy. Except if you use old streams (node 0.8) but i assume it is not the case.

You should only do req.pipe(saxStream).