ReadableStream

注意:此功能在Web Workers中可用。

ReadableStream 接口是流 API的一部分,表示一个可读的字节数据流。Fetch API通过body属性提供了一个具体的 ReadableStream 实例Response对象。

ReadableStream 是一个可传输对象

构造函数

ReadableStream()

根据给定的处理程序创建并返回一个可读流对象。

实例属性

ReadableStream.locked 只读

返回一个布尔值,指示可读流是否锁定到某个读取器。

静态方法

ReadableStream.from() 实验性

从提供的可迭代或异步可迭代对象(例如数组、集合、异步生成器等)返回 ReadableStream

实例方法

ReadableStream.cancel()

返回一个Promise,该 Promise 在流被取消时解析。调用此方法表示消费者不再对流感兴趣。提供的 reason 参数将传递给底层源,底层源可能会使用它也可能不会使用它。

ReadableStream.getReader()

创建一个读取器并将流锁定到它。在流被锁定期间,无法获取其他读取器,直到当前读取器被释放。

ReadableStream.pipeThrough()

提供了一种可链接的方式,用于将当前流通过转换流或任何其他可写/可读对进行管道传输。

ReadableStream.pipeTo()

将当前 ReadableStream 管道传输到给定的WritableStream并返回一个Promise,该 Promise 在管道传输过程成功完成时完成,或者在遇到任何错误时拒绝。

ReadableStream.tee()

tee 方法分流此可读流,返回一个包含两个结果分支作为新 ReadableStream 实例的双元素数组。这两个流中的每一个都接收相同的数据。

异步迭代

ReadableStream 实现异步可迭代协议。这使得可以使用for await...of语法异步迭代流中的块。

js
const stream = new ReadableStream(getSomeSource());

for await (const chunk of stream) {
  // Do something with each 'chunk'
}

异步迭代器消耗流,直到流用尽数据或以其他方式终止。循环也可以由于 breakthrowreturn 语句提前退出。

在迭代过程中,流被锁定以防止其他消费者获取读取器(尝试迭代已经锁定的流将抛出 TypeError)。当循环退出时,此锁将被释放。

默认情况下,退出循环也将取消流,以便它不能再被使用。要在退出循环后继续使用流,请将 { preventCancel: true } 传递到流的 values() 方法。

js
for await (const chunk of stream.values({ preventCancel: true })) {
  // Do something with 'chunk'
  break;
}
// Acquire a reader for the stream and continue reading ...

示例

获取流

在以下示例中,创建了一个人工Response,用于将从另一个资源获取的 HTML 片段流式传输到浏览器。

它演示了 ReadableStreamUint8Array结合使用的用法。

js
fetch("https://www.example.org")
  .then((response) => response.body)
  .then((rb) => {
    const reader = rb.getReader();

    return new ReadableStream({
      start(controller) {
        // The following function handles each data chunk
        function push() {
          // "done" is a Boolean and value a "Uint8Array"
          reader.read().then(({ done, value }) => {
            // If there is no more data to read
            if (done) {
              console.log("done", done);
              controller.close();
              return;
            }
            // Get the data and send it to the browser via the controller
            controller.enqueue(value);
            // Check chunks by logging to the console
            console.log(done, value);
            push();
          });
        }

        push();
      },
    });
  })
  .then((stream) =>
    // Respond with our stream
    new Response(stream, { headers: { "Content-Type": "text/html" } }).text(),
  )
  .then((result) => {
    // Do things with result
    console.log(result);
  });

将迭代器或异步迭代器转换为流

from() 静态方法可以将迭代器(例如ArrayMap)或(异步)迭代器转换为可读流。

js
const myReadableStream = ReadableStream.from(iteratorOrAsyncIterator);

在不支持 from() 方法的浏览器上,您可以创建自己的自定义可读流来实现相同的结果。

js
function iteratorToStream(iterator) {
  return new ReadableStream({
    async pull(controller) {
      const { value, done } = await iterator.next();

      if (value) {
        controller.enqueue(value);
      }
      if (done) {
        controller.close();
      }
    },
  });
}

警告:此示例假设返回值(当 donetrue 时为 value),如果存在,也是要入队的块。某些迭代器 API 可能将返回值用于不同的目的。您可能需要根据您正在交互的 API 调整代码。

使用 for await...of 对流进行异步迭代

此示例显示了如何使用for await...of循环迭代到达的块来处理 fetch() 响应。

js
const response = await fetch("https://www.example.org");
let total = 0;

// Iterate response.body (a ReadableStream) asynchronously
for await (const chunk of response.body) {
  // Do something with each chunk
  // Here we just accumulate the size of the response.
  total += chunk.length;
}

// Do something with the total
console.log(total);

规范

规范
流标准
# rs-class

浏览器兼容性

BCD 表格仅在启用 JavaScript 的浏览器中加载。

另请参阅