Ajax 简明教程
Stream API - Readable Streams
在 Stream API 中,可读流是我们可以顺序且异步地从中读取数据的数据源。它是从底层来源获取数据的一种标准化方式。底层来源是网络上存在的资源。它们有以下两种类型:
Push source − 在这种情况下,当你访问数据时,数据会推送到你那里。你可以控制流,比如何时开始或何时暂停,甚至何时终止当前流。例如,视频游戏流。
Pull source − 在这种情况下,你需要明确地向它们请求数据。例如,使用 Fetch 或 XHR 调用访问文件。
在可读流中,数据以小块的形式存在,因此一次一个块地顺序读取。一个块可以是一个字节,也可以是更大的大小。因此,数据块的大小在流中可以不同。现在让我们了解可读流如何工作。
Working of Readable Stream
可读流的工作非常直接。在可读流中,数据块被放置在队列中。这意味着这些块正在等待读取队列。这里我们有另一个队列,这是一个内部队列,用于跟踪未读块。这些块由读者读取。它一次处理一个块的数据,并允许你对数据执行操作。一个读者一次只能读取一个流。当读者开始读取流时,该流就被锁定,该读者表示不允许其他读者读取该流。如果你希望另一个读者读取该流,则必须终止第一个读者或可以创建一个分流流。此外,每个读者都有自己的控制器,它允许你控制流,例如开始、关闭或暂停。
它还有一个使用者,负责处理从可读流接收的数据并对其进行处理,并且能够对其进行操作。
Readable Stream Interfaces
Stream API 支持三种类型的可读流接口:
-
ReableStream Interface
-
ReableStreamDefaultReader Interface
-
ReadableStreamDefaultController Interface
Syntax
const newRead = new ReadableStream()
Or
const newRead = new ReadableStream(UnderlyingSource)
Or
const newRead = new ReadableStream(UnderlyingSource, QueuingStrategy)
以下是 ReadableStream() 构造函数的可选参数:
UnderlyingSource − 这个对象提供了各种方法和属性,它们定义了流实例的行为。这些方法是:start()、pull() 和 cancel(),而这些属性是:type 和 autoAllocateChunkSize。
QueuingStrategy −此对象用于为给定的流定义排队策略。它采用两个参数:highWaterMark 和 size(chunk)。
Instance Properties
ReadableStream 接口提供的属性为只读属性。因此 ReadableStream 提供的属性为:
Sr.No. |
Property & Description |
1 |
ReadableStream.locked 此属性用于检查可读流是否已被锁定到某个读者。 |
Methods
以下为 ReadableStream 接口常用的方法:
Sr.No. |
Method & Description |
1 |
ReadableStream.cancel() 此方法返回一个 Promise,当该流已取消时该 Promise 会完成。 |
2 |
ReadableStream.getReader() 此方法用于创建一个读者并将其锁定到该流。在释放此读者之前,不允许有其他读者。 |
3 |
ReadableStream.pipeThrough() 此方法用于创建一个可链式的方式,以将当前流通过一个转换流进行传输。 |
4 |
ReadableStream.pipeTo() 此方法用于将当前 ReadableStream 传输到给定的 WriteableStream。如果传输过程成功完成,则它将返回一个 Promise;如果由于某个错误而导致传输失败,则它将对其进行拒绝。 |
5 |
ReadableStream.tee() 此方法用于获取一个包含两个结果分支的双元素数组,这两个分支作为新的 ReadableStream 对象。 |
ReadableStreamDefaultReader Interface
ReadableStreamDefaultReader 接口用于表示一个默认读者,此默认读者会从网络中读取流数据。它也可以从 ReadableStream 读取。
Constructor
为了创建一个 readableStreamDefualtReader 对象,ReadableStreamDefaultReader 接口提供了一个 ReadableStreamDefaultReader() 构造函数。
Syntax
const newRead = new ReadableStreamDefaultReader(myStream)
此构造函数仅包含一个参数,它便是 myStream。它将读取 ReadableStream。
Instance Properties
ReadableStreamDefaultReader 接口提供的属性为只读属性。因此 ReadableStreamDefaultReader 提供的属性为:
Sr.No. |
Property & Description |
1 |
ReadableStreamDefaultReader.closed 此属性返回一个 Promise,当该流因某个错误而关闭或被拒绝时,该 Promise 会完成。这允许你编写一个程序,该程序将在流处理过程结束时做出响应。 |
Methods
以下为 ReadableStream 接口常用的方法:
Sr.No. |
Method & Description |
1 |
ReadableStreamDefaultReader.cancel() 此方法返回一个 Promise,当该流已取消时该 Promise 会完成。 |
2 |
ReadableStreamDefaultReader.read() 此方法返回一个 Promise,该 Promise 将提供对流队列中的下一个区块或数据块的访问。 |
3 |
ReadableStreamDefaultReader.releaseLock() 此方法用于取消该流上读者的锁定。 |
ReadableStreamDefaultController Interface
ReadableStreamDefaultController 接口表示一个控制器,它允许我们控制 ReadableStream 状态或内部队列。它不提供任何控制器,并且在构造 ReadableStream 时会自动创建该实例。
Instance Properties
Sr.No. |
Property & Description |
1 |
ReadableStreamDefaultController.desiredSize 此属性用于查找填充流内部队列所需的容量大小。 |
ReadableStreamDefaultController 接口提供的属性为只读属性。因此 ReadableStreamDefaultController 提供的属性为:
Methods
以下是 ReadableStreamDefaultController 接口常用的方式 -
Sr.No. |
Property & Description |
1 |
ReadableStreamDefaultController.close() 此方法用于关闭相关流。 |
2 |
ReadableStreamDefaultController.enqueue() 此方法用于将指定数据块或片段放入相关流中。 |
3 |
ReadableStreamDefaultController.error() 此方法将导致任何未来的交互与相关流到错误。 |
Example - Creating ReadableStream
在以下程序中,我们将使用 ReadableStream 构造函数创建一个自定义可读流。因此,我们首先创建了一个以块为单位生成数据的函数。然后,我们使用包含 start() 函数的 ReadableStream() 构造函数创建一个可读流。此 start() 函数使用 pData() 递归函数,该函数通过控制器将 myData() 功能中的数据推给使用者,其中每个推送操作之间设置 1 秒的超时。现在,我们使用 getReader() 函数创建读取器以使用流中的数据。然后,我们创建一个 readMyData() 函数,以在读者的帮助下从流中递归读取数据。流结束时,完成标志设置为 true,我们退出递归循环。
<!DOCTYPE html>
<html>
<body>
<script>
// Function that produces data for the stream
function* myData() {
yield 'pink';
yield 'blue';
yield 'yellow';
yield 'green';
}
// Create a readable stream using ReadableStream() function
const readStream = new ReadableStream({
start(controller) {
const data = myData();
// Adding data to the stream
function pData() {
const { done, value } = data.next();
if (done) {
// Close the stream if no more data is available
controller.close();
return;
}
// Pushing the data to the consumer
controller.enqueue(value);
// Continue pushing data after 1 sec
setTimeout(pData, 1000);
}
// Calling the pData function to start pushing data
pData();
}
});
// Create a reader for the readable stream
const myreader = readStream.getReader();
function readMyData() {
myreader.read().then(({ done, value }) => {
if (done) {
// Stream is closed
console.log('Stream is closed');
return;
}
// Processing the received data
console.log('Received data:', value);
// Continue reading the data
readMyData();
});
}
// Calling readMyData() function to start
// reading data from the readable stream
readMyData();
</script>
</body>
</html>