ReadableStreamBYOBReader: read() 方法
注意:此功能在 Web Workers 中可用。
read() 方法是 ReadableStreamBYOBReader 接口的一个方法,用于从关联的 可读字节流 中读取数据到一个用户提供的缓冲区视图。如果流的内部队列中有数据,则数据请求将从队列中满足。如果队列为空,则请求可能会直接从底层字节源进行零拷贝传输。
该方法接受一个视图作为参数,该视图指定了要将数据读取到哪个缓冲区中,并返回一个 Promise。当数据可用或流被取消时,该 Promise 会以一个包含 value 和 done 属性的对象进行 fulfilled。如果流发生错误,Promise 会以相关的错误对象进行 rejected。
当提供一个数据块时,value 属性将包含一个新的视图。这个视图将与传递给 read() 方法的原始 view 具有相同的缓冲区/底层内存,并且类型也相同,只是现在填充了新的数据块。请注意,一旦 Promise fulfilled,传递给方法的原始 view 将被分离,不再可用。如果流被取消,Promise 将以 value: undefined fulfilled。在这种情况下,view 的底层内存区域将被丢弃,不会返回给调用者(视图缓冲区中所有先前读取的数据都将丢失)。
done 属性指示是否还期望有更多数据。如果流已关闭或被取消,则值为 true,否则为 false。
该方法还有一个可选的 options.min 参数,可用于指定在流处于活动状态时,必须有多少个元素可用后 Promise 才会 fulfilled。在 value 属性中返回的视图将始终至少包含此数量的元素,除非流已关闭。
语法
read(view)
read(view, options)
参数
view-
要将数据读取到的视图。
options可选-
选项如下:
min-
在流处于活动状态时,在 Promise fulfilled 之前必须读取的最少元素数量。如果未提供,Promise 将在至少读取一个元素(最多视图的最大尺寸)后 resolve。此数字不得大于正在读取的视图。
返回值
一个 Promise,它会根据流的状态 fulfilled/rejected。结果对象包含两个属性:value 和 done。
以下是可能的情况:
-
如果有一个数据块可用且流仍处于活动状态,则结果的
done为false,value是一个包含新数据的视图。这是与传递给read()方法的view类型相同且在同一底层内存上的视图。原始view将被分离,不再可用。 -
如果流已关闭,则结果的
done为true,value具有与上述相同的属性。 -
如果流被取消,则结果的
done为true,value为undefined。在这种情况下,底层内存将被丢弃。 -
如果流抛出错误,Promise 将以相关的错误 rejection。
异常
TypeError-
源对象不是
ReadableStreamBYOBReader,流没有所有者,视图不是对象或已失效,视图的长度为 0,options.min为 0,或者调用了ReadableStreamBYOBReader.releaseLock()(当存在待处理的读取请求时)。 RangeError-
options.min值大于正在写入的视图。
示例
读取到视图中
这里的示例代码摘自 使用可读字节流 中的实时示例。
首先,我们通过在流上调用 ReadableStream.getReader() 来创建 reader,并在选项参数中指定 mode: "byob"。我们还需要创建一个 ArrayBuffer,它是我们将要写入的视图的“底层内存”。
const reader = stream.getReader({ mode: "byob" });
let buffer = new ArrayBuffer(4000);
下面是一个使用 reader 的函数。该函数递归调用 read() 方法将数据读入缓冲区。该方法接受一个 Uint8Array 类型数组,它是原始数组缓冲区中尚未写入部分的一个视图。视图的参数是根据之前调用接收到的数据计算的,这些数据定义了原始数组缓冲区的偏移量。
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
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 |
浏览器兼容性
加载中…