使用 Web Streams,从多个 TransformStream 创建一个 TransformStream

Shr*_*gie 5 javascript whatwg-streams-api

是否可以使用 Whatwg Streams(Web Streams API )从其他几个 TransformStream 中创建一个TransformStream

例如,如果我有两个按顺序运行的 TransformStream,如transformer1transformer2

readable.pipeThrough(transformer1).pipeThrough(transformer2).pipeTo(writable)
Run Code Online (Sandbox Code Playgroud)

最终,我希望能够将其转换为

readable.pipeThrough(allTransformers).pipeTo(writable)
Run Code Online (Sandbox Code Playgroud)

allTransformersTransformStream 组合transformer1和 的位置在哪里transformer2

下面不是真正的功能代码,但我认为有一种方法可以做到这样的事情:

const allTransformers = transformer1.pipeThrough(transformer2)
Run Code Online (Sandbox Code Playgroud)

这显然是一个简化的示例,但您可以想象有许多转换流,我想重构为单个可重用的转换管道。

che*_*_ca 8

我遇到了同样的问题,这是我的解决方案。

在下面的示例中,通过、和UpperCaseTransformStream管道传输流。TextDecoderStreamUpperCaseTextStreamTextEncoderStream

class UpperCaseTextStream extends TransformStream {
  constructor() {
    super({
      transform(chunk, controller) {
        controller.enqueue(chunk.toUpperCase());
      }
    });
  }
}

class UpperCaseTransformStream {
  constructor(...strategies) {
    const { writable, readable } = new TransformStream({}, ...strategies);
    this.writable = writable;
    this.readable = readable
      .pipeThrough(new TextDecoderStream())
      .pipeThrough(new UpperCaseTextStream())
      .pipeThrough(new TextEncoderStream());
  }
}

const TEXT_CHUNK =
 "Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy " +
 "nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.";
const TEXT_CONTENT = new Array(1024 * 1024).fill(TEXT_CHUNK).join("");
const readableInput = new Blob([TEXT_CONTENT]).stream();
const readableOuput = readableInput.pipeThrough(new UpperCaseTransformStream());  
(async () => {
  const text = await new Response(readableOuput).text();
  console.log("Test OK?", text == TEXT_CONTENT.toUpperCase());
})().catch(console.error);
Run Code Online (Sandbox Code Playgroud)

PipelineStream这是一个更通用的实现,使用扩展TransformStream并接受实例数组作为第一个参数的类TransformStream

class UpperCaseTextStream extends TransformStream {
  constructor() {
    super({
      transform(chunk, controller) {
        controller.enqueue(chunk.toUpperCase());
      }
    });
  }
}

class PipelineStream extends TransformStream {
  constructor(transformStreams, ...strategies) {
    super({}, ...strategies);

    const readable = [super.readable, ...transformStreams]
      .reduce((readable, transform) => readable.pipeThrough(transform));

    Object.defineProperty(this, "readable", {
      get() {
        return readable;
      }
    });
  }
}

const TEXT_CHUNK =
 "Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy " +
 "nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.";
const TEXT_CONTENT = new Array(1024 * 1024).fill(TEXT_CHUNK).join("");
const readableInput = new Blob([TEXT_CONTENT]).stream();
const readableOuput = readableInput.pipeThrough(new PipelineStream([
  new TextDecoderStream(),
  new UpperCaseTextStream(),
  new TextEncoderStream()]));
(async () => {
  const text = await new Response(readableOuput).text();
  console.log("Test OK?", text == TEXT_CONTENT.toUpperCase());
})().catch(console.error);
Run Code Online (Sandbox Code Playgroud)