ReadableStream
Baseline 广泛可用 *
注意:此功能在 Web Workers 中可用。
ReadableStream 接口是 Streams API 的一部分,代表一个可读的字节数据流。 Fetch API 通过 body 属性提供了一个 ReadableStream 的具体实例,该属性是 Response 对象的一部分。
ReadableStream 是一个 可转移对象。
构造函数
ReadableStream()-
从给定的处理程序创建并返回一个可读流对象。
实例属性
ReadableStream.locked只读-
返回一个布尔值,指示可读流是否已被读取器锁定。
静态方法
ReadableStream.from()实验性-
从提供的可迭代对象或异步可迭代对象(如数组、集合、异步生成器等)返回
ReadableStream。
实例方法
ReadableStream.cancel()-
返回一个
Promise,当流被取消时解析。调用此方法表示消费者对该流不再感兴趣。提供的reason参数将传递给底层源,源可能会也可能不会使用它。 ReadableStream.getReader()-
创建一个读取器并将流锁定到该读取器。当流被锁定后,在释放此读取器之前,不能获取其他读取器。
ReadableStream.pipeThrough()-
提供了一种链式方式,将当前流通过转换流或任何其他可写/可读对进行管道传输。
ReadableStream.pipeTo()-
将当前 ReadableStream 管道传输到指定的
WritableStream,并返回一个Promise。当管道传输成功完成时,该 Promise 会 fulfilled;如果遇到任何错误,则会 rejected。 ReadableStream.tee()-
tee方法 将此可读流进行分叉,返回一个包含两个新ReadableStream实例的两个元素的数组。这两个流接收相同的数据。
异步迭代
ReadableStream 实现 异步迭代协议。这使得可以使用 for await...of 语法异步迭代流中的块。
const stream = new ReadableStream(getSomeSource());
for await (const chunk of stream) {
// Do something with each 'chunk'
}
异步迭代器会消耗流,直到它没有更多数据或终止。循环也可以由于 break、throw 或 return 语句而提前退出。
在迭代期间,流会被锁定,以防止其他消费者获取读取器(尝试迭代一个已被锁定的流将抛出 TypeError)。此锁在循环退出时会被释放。
默认情况下,退出循环也会取消流,使其无法再被使用。要在退出循环后继续使用流,请将 { preventCancel: true } 传递给流的 values() 方法。
for await (const chunk of stream.values({ preventCancel: true })) {
// Do something with 'chunk'
break;
}
// Acquire a reader for the stream and continue reading ...
示例
Fetch 流
在以下示例中,创建了一个人工 Response 对象,以将从其他资源获取的 HTML 片段流式传输到浏览器。
它演示了 ReadableStream 与 Uint8Array 结合使用的用法。
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() 静态方法可以将迭代器(如 Array 或 Map)或 (异步)迭代器 转换为可读流。
const myReadableStream = ReadableStream.from(iteratorOrAsyncIterator);
在不支持 from() 方法的浏览器中,您可以改为创建自己的 自定义可读流 来达到相同的效果。
function iteratorToStream(iterator) {
return new ReadableStream({
async pull(controller) {
const { value, done } = await iterator.next();
if (value) {
controller.enqueue(value);
}
if (done) {
controller.close();
}
},
});
}
警告:此示例假定返回值(在 done 为 true 时为 value)如果存在,也应视为要入队的块。某些迭代器 API 可能将返回值用于不同目的。您可能需要根据您交互的 API 来调整代码。
使用 for await...of 对流进行异步迭代
此示例演示了如何使用 for await...of 循环处理 fetch() 响应,以迭代到达的块。
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);
规范
| 规范 |
|---|
| Streams # rs-class |
浏览器兼容性
加载中…