ReadableStream

Stream API 中的 ReadableStream 接口表示可读的字节数据流。Fetch API 通过 Response 的属性 body (en-US) 提供了一个具体的 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 (en-US) 的协同用法。

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

参见