Javascript 定义web流源/汇逻辑的最佳方法是什么?

Javascript 定义web流源/汇逻辑的最佳方法是什么?,javascript,stream,Javascript,Stream,我正在使用新的web streams polyfill,我不清楚定义和/或向web streams添加扩展功能的最佳方法。尤其是如果溪流有点长寿的话 特别是,作为一个不错的例子,我想使用webRTC数据通道作为可读的流源。该数据通道可以通过背压或编程方式暂停 我在规范和实验中发现了一些可能的模式: 扩展流类: 我遇到的一个问题是必须将源方法传递到super而不引用它,这是必需的,因为它在super调用之前。一个好处似乎是,您生成的流将直接在其上有额外的暂停/恢复方法 单独定义源,包装源以用作流:

我正在使用新的web streams polyfill,我不清楚定义和/或向web streams添加扩展功能的最佳方法。尤其是如果溪流有点长寿的话

特别是,作为一个不错的例子,我想使用webRTC数据通道作为可读的流源。该数据通道可以通过背压或编程方式暂停

我在规范和实验中发现了一些可能的模式:

扩展流类: 我遇到的一个问题是必须将源方法传递到super而不引用它,这是必需的,因为它在super调用之前。一个好处似乎是,您生成的流将直接在其上有额外的暂停/恢复方法

单独定义源,包装源以用作流: 在这种模式中,额外的方法附加到源,而不是流,这使得不那么引人注目,但可能更显式 api

只需使用使用流的自定义类,但实际上不是源: 我真的不喜欢在这里重新定义PipeToAPI,但我们也可以做一些类似getStream的事情并返回流

最后一点,我有点希望我们可以扩展基类并将源方法定义为子类的成员,而不是将它们传递给超级类。有没有理由不允许这种设计

class DataChannelStream extends ReadableStream {
  constructor(dataChannel) {
    super()
    this.dataChannel = dataChannel
  }

  // source methods
  start: () => { ... }
  pull: () => { ... }
  cancel: () => { ... }  

  // extra methods
  pause() { ... }
  resume() { ... }
}
鉴于上面的例子,前三种模式似乎可以工作,但显然提供了不同的API。因此,它可能最终归结为品味/设计


我想知道是否有人可以帮助指导我的预期用途,或者是否有人提出了最佳实践

我建议使用选项3的变体,其中使用名为readable的getter返回流,以与web标准保持一致

有关此类API的示例,请参见

选项1将提供很好的易用性,但我不喜欢使用实现的继承,正如您所提到的,构建它将很棘手

选项2对我来说就像是一个样板

在ReadableStream对象上未公开start、pull和cancel的原因是在创建流的API和使用流的API之间提供了一个清晰的分离

杰克·阿奇博尔德(Jake Archibald)的《2016年——网络流年》(the year of web streams)是我所知道的关于如何在流中思考的最好的文章,但我渴望听到其他任何文章

class DataChannelSource {
  constructor(dataChannel) {
    this.dataChannel = dataChannel
  }
  // source methods
  start: () => { ... }
  pull: () => { ... }
  cancel: () => { ... }  

  // extra methods
  pause() { ... }
  resume() { ... }
}

// elsewhere....
function createDataChannelStream (dataChannel) {
  const source = new DataChannelSource(dataChannel)
  const stream = new ReadableStream(source)
  return { source, stream }
}
class DataChannelSource {
  constructor(dataChannel) {
    this.dataChannel = dataChannel
  }

  pipeTo(dest) {
    const stream = new ReadableStream({
      // source methods
      start: () => { ... }
      pull: () => { ... }
      cancel: () => { ... }  
    })
    return stream.pipeTo(dest)
  }

  // extra methods
  pause() { ... }
  resume() { ... }
}
class DataChannelStream extends ReadableStream {
  constructor(dataChannel) {
    super()
    this.dataChannel = dataChannel
  }

  // source methods
  start: () => { ... }
  pull: () => { ... }
  cancel: () => { ... }  

  // extra methods
  pause() { ... }
  resume() { ... }
}