ReadableStreamBYOBReader: read() 方法

可用性有限

此特性不是基线特性,因为它在一些最广泛使用的浏览器中不起作用。

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

read() 方法是 ReadableStreamBYOBReader 接口的一个方法,用于从关联的 可读字节流 中读取数据到一个用户提供的缓冲区视图。如果流的内部队列中有数据,则数据请求将从队列中满足。如果队列为空,则请求可能会直接从底层字节源进行零拷贝传输。

该方法接受一个视图作为参数,该视图指定了要将数据读取到哪个缓冲区中,并返回一个 Promise。当数据可用或流被取消时,该 Promise 会以一个包含 valuedone 属性的对象进行 fulfilled。如果流发生错误,Promise 会以相关的错误对象进行 rejected。

当提供一个数据块时,value 属性将包含一个新的视图。这个视图将与传递给 read() 方法的原始 view 具有相同的缓冲区/底层内存,并且类型也相同,只是现在填充了新的数据块。请注意,一旦 Promise fulfilled,传递给方法的原始 view 将被分离,不再可用。如果流被取消,Promise 将以 value: undefined fulfilled。在这种情况下,view 的底层内存区域将被丢弃,不会返回给调用者(视图缓冲区中所有先前读取的数据都将丢失)。

done 属性指示是否还期望有更多数据。如果流已关闭或被取消,则值为 true,否则为 false

该方法还有一个可选的 options.min 参数,可用于指定在流处于活动状态时,必须有多少个元素可用后 Promise 才会 fulfilled。在 value 属性中返回的视图将始终至少包含此数量的元素,除非流已关闭。

语法

js
read(view)
read(view, options)

参数

view

要将数据读取到的视图。

options 可选

选项如下:

min

在流处于活动状态时,在 Promise fulfilled 之前必须读取的最少元素数量。如果未提供,Promise 将在至少读取一个元素(最多视图的最大尺寸)后 resolve。此数字不得大于正在读取的视图。

返回值

一个 Promise,它会根据流的状态 fulfilled/rejected。结果对象包含两个属性:valuedone

以下是可能的情况:

  • 如果有一个数据块可用且流仍处于活动状态,则结果的 donefalsevalue 是一个包含新数据的视图。这是与传递给 read() 方法的 view 类型相同且在同一底层内存上的视图。原始 view 将被分离,不再可用。

  • 如果流已关闭,则结果的 donetruevalue 具有与上述相同的属性。

  • 如果流被取消,则结果的 donetruevalueundefined。在这种情况下,底层内存将被丢弃。

  • 如果流抛出错误,Promise 将以相关的错误 rejection。

异常

TypeError

源对象不是 ReadableStreamBYOBReader,流没有所有者,视图不是对象或已失效,视图的长度为 0,options.min 为 0,或者调用了 ReadableStreamBYOBReader.releaseLock()(当存在待处理的读取请求时)。

RangeError

options.min 值大于正在写入的视图。

示例

读取到视图中

这里的示例代码摘自 使用可读字节流 中的实时示例。

首先,我们通过在流上调用 ReadableStream.getReader() 来创建 reader,并在选项参数中指定 mode: "byob"。我们还需要创建一个 ArrayBuffer,它是我们将要写入的视图的“底层内存”。

js
const reader = stream.getReader({ mode: "byob" });
let buffer = new ArrayBuffer(4000);

下面是一个使用 reader 的函数。该函数递归调用 read() 方法将数据读入缓冲区。该方法接受一个 Uint8Array 类型数组,它是原始数组缓冲区中尚未写入部分的一个视图。视图的参数是根据之前调用接收到的数据计算的,这些数据定义了原始数组缓冲区的偏移量。

js
readStream(reader);

function readStream(reader) {
  let bytesReceived = 0;
  let offset = 0;

  while (offset < buffer.byteLength) {
    // read() returns a promise that fulfills when a value has been received
    reader
      .read(new Uint8Array(buffer, offset, buffer.byteLength - offset))
      .then(function processBytes({ done, value }) {
        // Result objects contain two properties:
        // done  - true if the stream has already given all its data.
        // value - some data. 'undefined' if the reader is canceled.

        if (done) {
          // There is no more data in the stream
          return;
        }

        buffer = value.buffer;
        offset += value.byteLength;
        bytesReceived += value.byteLength;

        // Read some more, and call this function again
        // Note that here we create a new view over the original buffer.
        return reader
          .read(new Uint8Array(buffer, offset, buffer.byteLength - offset))
          .then(processBytes);
      });
  }
}

当流中没有更多数据时,read() 方法将以 done 属性设置为 true 的对象 fulfilled,然后函数返回。

读取最少数量的元素

此示例与上一个示例几乎完全相同,只是我们修改了代码,使每次迭代读取最少 101 个元素。

我们还将其制作成了一个实时示例。请注意,大部分代码与示例无关,因此被隐藏了。有关更多信息,请参阅 使用可读字节流

JavaScript

js
function readStream(reader) {
  let bytesReceived = 0;
  let offset = 0;

  while (offset < buffer.byteLength) {
    // read() returns a promise that resolves when a value has been received
    reader
      .read(new Uint8Array(buffer, offset, buffer.byteLength - offset), {
        min: 101,
      })
      .then(async function processText({ done, value }) {
        // Result objects contain two properties:
        // done  - true if the stream has already given all its data.
        // value - some data. Always undefined when done is true.

        if (done) {
          logConsumer(
            `readStream() complete. Read ${value.byteLength} bytes (total: ${bytesReceived})`,
          );
          return;
        }

        buffer = value.buffer;
        offset += value.byteLength;
        bytesReceived += value.byteLength;

        // logConsumer(`Read ${bytesReceived} bytes: ${value}`);
        logConsumer(`Read ${value.byteLength} bytes (total: ${bytesReceived})`);
        result += value;

        // Read some more, and call this function again
        return reader
          .read(new Uint8Array(buffer, offset, buffer.byteLength - offset), {
            min: 101,
          })
          .then(processText);
      });
  }
}

结果

下面显示了底层推送源(左)和消费者(右)的日志记录。请注意,如果浏览器支持 options.min 参数,那么每次将返回至少 101 个元素(通常更多),除非流关闭。

规范

规范
Streams
# byob-reader-read

浏览器兼容性

另见