ReadableStream

Baseline 2022

Newly available

Since June 2022, this feature works across the latest devices and browser versions. This feature might not work in older devices or browsers.

Stream API 中的 ReadableStream 接口表示可读的字节数据流。Fetch API 通过 Response 的属性 body 提供了一个具体的 ReadableStream 对象。

构造函数

ReadableStream()

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

实例属性

ReadableStream.locked 只读

locked 返回该可读流是否被锁定到一个 reader。

实例方法

ReadableStream.cancel()

取消读取流,读取方发出一个信号,表示对这束流失去兴趣。可以传入 reason 参数表示取消原因,这个原因将传回给调用方。

ReadableStream.getReader()

创建一个读取器并将流锁定于其上。一旦流被锁定,其他读取器将不能读取它,直到它被释放。

ReadableStream.pipeThrough()

提供将当前流管道输出到一个转换(transform)流或可写/可读流对的链式方法。

ReadableStream.pipeTo()

将当前 ReadableStream 管道输出到给定的 WritableStream,并返回一个 promise,该 promise 在输出过程成功完成时兑现,在发生错误时拒绝。

ReadableStream.tee()

tee 方法拷贝了可读流,返回包含两个 ReadableStream 实例分支的数组,每个元素接收了相同的传输数据。

示例

Fetch 流

下面的例子,创建了一个智能的 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);
  });

转换异步迭代器到流

(异步)迭代器转换为可读流:

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

这适用于异步和非异步的迭代器。

使用 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);

规范

Specification
Streams Standard
# rs-class

浏览器兼容性

BCD tables only load in the browser

参见