如何创建一个Node.js代理可读流来包装另一个';在创建代理流时,s不可用?

如何创建一个Node.js代理可读流来包装另一个';在创建代理流时,s不可用?,node.js,stream,Node.js,Stream,我可以发出一个简单的HTTP请求并返回一个流 但是,如果我必须发出一个HTTP请求,然后轮询以确定数据是否准备好,然后再发出另一个请求以获取数据,该怎么办 我想在一个返回流的方法中完成这一切,这样我就可以: multiStepMethod(options).pipe(wherever); 而不是: multiStepMethod(options, (err, stream) => { stream.pipe(wherever); }) 我需要multiStepMethod返回一

我可以发出一个简单的HTTP请求并返回一个流

但是,如果我必须发出一个HTTP请求,然后轮询以确定数据是否准备好,然后再发出另一个请求以获取数据,该怎么办

我想在一个返回流的方法中完成这一切,这样我就可以:

multiStepMethod(options).pipe(wherever);
而不是:

multiStepMethod(options, (err, stream) => {
    stream.pipe(wherever);
})
我需要multiStepMethod返回一个代理可读流,该流将等待某个事件,然后包装(现在可用)流并开始将其数据发送到管道中。

#/usr/bin/env节点
#!/usr/bin/env node

'use strict';

const stream = require('stream');

// This is an example of a 'readable' stream that has to go through a multi-
// step process to finally get the actual readable stream. So we are
// asynchronously wrapping another readable stream.

// The key to simplicity here was to use a transform stream instead of a
// readable stream because it allows us to pipe the stream to ourselves.
class ReadableWrappingTransform extends stream.Transform {
  constructor() {
    super({
      objectMode: true,
      // Our _transform method doesn't really do anything and we don't want to
      // hog up any more additional memory than necessary.
      highWaterMark: 1
    });
    process.nextTick(() => {
      if (new Date().getTime() % 5 === 1) {

        // Here we simulate an error that happened somewhere in the multi-step
        // process to get the final stream. So we just emit 'error' and we're
        // done.
        this.emit('error', new Error('Could not get the stream.'));

        //Assuming based on the node docs that we should not emit
        // 'close' or 'end' on error. If we do emit 'end', it will trigger the
        // writable's 'finish' event, which is probably not desired. You either
        // want an 'error' OR a 'finish'.

        // NODE END EVENT DOCS
        // The 'end' event is emitted when there is no more data to be consumed
        // from the stream.

        // Note: The 'end' event will not be emitted unless the data is
        // completely consumed. This can be accomplished by switching the stream
        // into flowing mode, or by calling stream.read() repeatedly until all
        // data has been consumed.

        // this.emit('end');

        // NODE CLOSE EVENT DOCS
        // The 'close' event is emitted when the stream and any of its
        // underlying resources (a file descriptor, for example) have been
        // closed. The event indicates that no more events will be emitted, and
        // no further computation will occur.

        // Not all Readable streams will emit the 'close' event.

        // this.emit('close');
      } else {
        // We successfully got the stream we wanted after a long, hard, multi-
        // step process, so first we need to copy all our listeners over to it
        // -- NOT.

        // ['close', 'data', 'end', 'error'].forEach((eventName) => {
        //   this.listeners(eventName).forEach((l) => {
        //     readable.on(eventName, l);
        //   });
        // });

        // Turns out that .pipe propagates ALL listeners EXCEPT the 'error'
        // listener. What's up with that !?! If we copy any of the others  we
        // get double the events -- including double the data. So here we just
        // copy over the 'error' listener to make sure we get 'error' events.
        ['error'].forEach((eventName) => {
          this.listeners(eventName).forEach((l) => {
            readable.on(eventName, l);
          });
        });

        // Then just pipe the final readable to ourselves, and we are good.
        readable
          .pipe(this);
      }
    });
  }
  _transform(data, encoding, callback) {
    // Nothing special to do here just pass along the data.
    this.push(data);
    callback();
  }
}

// This is just a very unreliable test readable stream.
const readable = new stream.Readable({
  objectMode: true,
  read() {
    for (let i = 0; i < 10; i++) {
      if (new Date().getTime() % 13 === 1) {
        this.__err = new Error('Sorry, error reading data.');
        this.emit('error', this.__err);
        return;
      }
      this.push({
        Name: `Mikey ${i}`
      });
    }
    this.push(null);
  }
});

// Any old writable that we can pipe to.
const writable = new stream.Writable({
  objectMode: true,
  write(chunk, encoding, callback) {
    console.log(chunk, encoding);
    callback();
  }
});

new ReadableWrappingTransform()
  // if your stream emits close you get close.
  .on('close', () => {
    console.error('CLOSE');
  })
  // if you push null you get end from read.
  .on('end', () => {
    console.error('END');
  })
  // error needs to be both places !?! seriously node?
  .on('error', (error) => {
    console.error('ERROR', error);
  })
  // Finish does no good here. It's a writable event.
  // .on('finish', () => {
  //   console.error('FINISH');
  // })
  .pipe(writable)
  // Close and End do no good here, they are readable events.
  // They are not propagated to the writable.
  //
  // // if your stream emits close you get close.
  // .on('close', () => {
  //   console.error('CLOSE');
  // })
  // // if you push null you get end from read.
  // .on('end', () => {
  //   console.error('END');
  // })
  // error needs to be both places !?! seriously node?
  .on('error', (error) => {
    console.error('ERROR', error);
  })
  // you should always get either finish or error or something was done
  // incorrectly.
  .on('finish', () => {
    console.error('FINISH');
  });
"严格使用",; const stream=require('stream'); //这是一个“可读”流的示例,它必须通过多个- //步骤处理,以最终获得实际的可读流。所以我们是 //异步包装另一个可读流。 //这里简单的关键是使用转换流而不是 //可读流,因为它允许我们通过管道将流传送给自己。 类ReadableWrappingTransform扩展了stream.Transform{ 构造函数(){ 超级({ objectMode:true, //我们的_变换方法实际上没有做任何事情,我们也不想做 //占用不必要的额外内存。 高水位:1 }); process.nextTick(()=>{ 如果(新日期().getTime()%5==1){ //在这里,我们模拟了多步骤过程中发生的错误 //进程以获取最终流。因此,我们只发出“error”,然后 //完成了。 this.emit('error',new error('无法获取流'); //假设基于我们不应该发出的节点文档 //出现错误时“关闭”或“结束”。如果我们发出“结束”,它将触发 //writable的“finish”事件,这可能是不需要的 //想要一个“错误”或“完成”。 //节点结束事件文档 //当没有更多数据要使用时,将发出“end”事件 //从小溪里。 //注意:“结束”事件将不会发出,除非数据 //完全消耗。这可以通过切换流来实现 //进入流动模式,或通过反复调用stream.read()直到所有 //数据已被消耗。 //这个.emit('end'); //节点关闭事件文档 //“close”事件在流及其任何 //底层资源(例如文件描述符)已被删除 //已关闭。该事件表示不再发出任何事件,并且 //不会进行进一步的计算。 //并非所有可读流都将发出“关闭”事件。 //这个.emit('close'); }否则{ //经过漫长、艰苦、多次的努力,我们成功地获得了我们想要的信息流- //第一步,我们需要将所有侦听器复制到它 //”“没有。 //['close','data','end','error'].forEach((eventName)=>{ //this.listeners(eventName).forEach((l)=>{ //可读。on(事件名称,l); // }); // }); //结果表明.pipe传播除“error”之外的所有侦听器 //听众,怎么回事!?!如果我们复制其他人的话 //获取双倍的事件,包括双倍的数据 //复制“错误”侦听器以确保获得“错误”事件。 ['error'].forEach((eventName)=>{ this.listeners(eventName).forEach((l)=>{ 可读。on(事件名称,l); }); }); //然后就把最后的可读性给我们自己,我们就好了。 可读的 .管道(本); } }); } _转换(数据、编码、回调){ //这里没有什么特别的事情,只是传递数据。 这个.推(数据); 回调(); } } //这只是一个非常不可靠的测试可读流。 const readable=新流。readable({ objectMode:true, 读(){ for(设i=0;i<10;i++){ 如果(新日期().getTime()%13==1){ 这是。uu err=新错误('对不起,读取数据时出错'); this.emit('error',this.\u err); 返回; } 这个,推({ 姓名:`Mikey${i}` }); } 这个.push(null); } }); //任何我们可以通过管道传输的旧可写文件。 const writable=新流。可写({ objectMode:true, 写入(块、编码、回调){ log(块,编码); 回调(); } }); 新的ReadableWrappingTransform() //如果你的溪流靠近,你就会靠近。 .on('关闭',()=>{ 控制台错误(“关闭”); }) //若你们按下null键,你们将从read中得到end。 .on('end',()=>{ console.error('END'); }) //错误必须是两个位置!?!认真点? .on('错误',(错误)=>{ console.error('error',error); }) //结束在这里没有好处。这是一个可写的事件。 //.on('finish',()=>{ //console.error('FINISH'); // }) .pipe(可写) //“结束”和“结束”在这里没有任何用处,它们是可读的事件。 //它们不会传播到可写对象。 // ////如果您的流发出接近的信号,您就接近了。 //.on('关闭',()=>{ //控制台错误(“关闭”); // }) ////如果按null键,则从读取中得到结束。 //.on('end',()=>{ //console.error('END'); // }) //错误必须是两个位置!?!认真点? .on('错误',(错误)=>{ console.error('error',error); }) //你应该总是得到要么完成,要么出错,要么完成了某件事 //不对。 .on('finish',()=>{ console.error('FINISH'); });
#/usr/bin/env节点
"严格使用",;
const stream=require('stream');
//这是一个“可读”流的示例,它必须通过多个-
//步骤处理,以最终获得实际的可读流。所以我们是
//异步包装另一个可读流。
//这里简单的关键是使用转换流而不是
//可读流贝库