Stream API - 可读流



在 Stream API 中,可读流是一个数据源,我们可以从中以顺序和异步的方式读取数据。这是从底层源获取数据的标准化方法。底层源是网络上存在的资源。它们有以下两种类型 -

  • 推送源 - 当您访问数据时,数据将推送给您。您可以控制流,例如何时开始或何时暂停,甚至何时终止当前流。例如,视频游戏流式传输。
  • 拉取源 - 您需要从他们那里明确请求数据。例如,在 Fetch 或 XHR 调用的帮助下访问文件。

在 Readable Stream 中,数据以小块的形式存在,因此它是按顺序读取的,一次读取一个块。块可以是单个字节,也可以是更大的大小。因此,流中块的大小可能不同。现在让我们了解 readable stream 是如何工作的。

可读流的工作原理

Readable 流的工作原理非常简单。在可读流中,数据块被放置在 enqueue 中。这意味着 chunk 正在队列中等待读取。这里我们还有另一个队列,它是一个内部队列,它跟踪未读的块。读取器读取 chunk。它一次处理一个块的数据,并允许您对数据执行操作。一个读取器一次只能读取一个流。当读取器开始读取流时,该读取器的流将被锁定,这意味着不允许其他读取器读取该流。如果您希望另一个读取器读取该流,则必须终止第一个读取器,或者可以创建 tee 流。此外,每个读取器都有自己的控制器,允许您控制流,例如 start、close 或 pause。

它还有一个使用者,负责处理从可读流接收到的数据并对其进行处理,并能够对其执行操作。

可读流

可读流接口

Stream API 支持三种类型的可读流接口 -

  • ReableStream 接口
  • ReableStreamDefaultReader 接口
  • ReadableStreamDefaultController 接口

ReadableStream 接口

ReadableStream 接口用于表示可读的数据流。它通常与 Fetch API 一起使用来处理响应流。它还可以处理开发人员定义的流的响应流。

构造 函数

为了为给定的处理程序创建可读的流对象,ReadableStream 接口提供了一个 ReadableStream() 构造函数。

语法


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)。

实例属性

ReadableStream 接口提供的属性是只读属性。所以 ReadableStream 提供的属性是 -

属性 描述
ReadableStream.locked

此属性用于检查可读流是否已锁定到读取器。

方法

以下是 ReadableStream 接口的常用方法 -

方法 描述
ReadableStream.cancel()

此方法返回一个 Promise,该 Promise 将在取消流时 resolve。

ReadableStream.getReader()

该方法用于创建读取器并将流锁定到它。在释放此读取器之前,不允许使用其他读取器。

ReadableStream.pipeThrough()

此方法用于创建一种通过 transform 流传输当前流的可链接方式。

ReadableStream.pipeTo()

此方法用于将当前 ReadableStream 通过管道传输到给定的 WriteableStream。当管道过程成功完成时,它将返回一个 promise,或者由于某些错误而被拒绝。

ReadableStream.tee()

此方法用于获取一个双元素数组,其中包括两个结果分支作为新的 ReadableStream 对象。

ReadableStreamDefaultReader 接口

ReadableStreamDefaultReader 接口用于表示将从网络读取流数据的默认读取器。它也可以从 ReadableStream 中读取。

构造 函数

要创建 readableStreamDefualtReader 对象,ReadableStreamDefaultReader 接口提供了一个 ReadableStreamDefaultReader () 构造函数。

语法


const newRead = new ReadableStreamDefaultReader(myStream)

此构造函数仅包含一个参数,即 myStream。它将读取 ReadableStream。

实例属性

ReadableStreamDefaultReader 接口提供的属性是只读属性。因此,ReadableStreamDefaultReader 提供的属性是 -

属性 描述
ReadableStreamDefaultReader.closed

此属性返回一个 Promise,当流由于某些错误而关闭或被拒绝时,该 Promise 将解决。它允许您编写一个程序,该程序将在流式处理过程结束时响应。

方法

以下是 ReadableStream 接口的常用方法 -

方法 描述
ReadableStreamDefaultReader.cancel()

此方法返回一个 Promise,该 Promise 将在取消流时 resolve。

ReadableStreamDefaultReader.read()

此方法返回一个 Promise,该 Promise 将允许访问流队列中的下一个块或块。

ReadableStreamDefaultReader.releaseLock()

该方法用于解除 reader 对 Stream 的锁定。

ReadableStreamDefaultController 接口

ReadableStreamDefaultController 接口表示一个控制器,它允许我们控制 ReadableStream State 或内部队列。它不提供任何控制器,实例是在构造 ReadableStream 时自动创建的。

实例属性

属性 描述
ReadableStreamDefaultController.desiredSize

此属性用于查找所需的大小以填充流的内部队列。

 

ReadableStreamDefaultController 接口提供的属性是只读属性。所以 ReadableStreamDefaultController 提供的属性是 -

方法

以下是 ReadableStreamDefaultController 接口的常用方法 -

属性 描述
ReadableStreamDefaultController.close()

该方法用于关闭相关流。

ReadableStreamDefaultController.enqueue()

此方法用于将相关流中的指定块或块入队。

ReadableStreamDefaultController.error()

此方法将导致将来与相关流的任何交互都出现错误。

示例 - 创建 ReadableStream

在下面的程序中,我们将使用 ReadableStream 构造函数创建自定义可读流。因此,首先我们创建一个以块形式生成数据的函数。然后,我们使用包含 start() 函数的 ReadableStream() 构造函数创建一个可读流。此 start() 函数使用 pData() 递归函数,该函数在控制器的帮助下将数据从 myData() 函数推送给使用者,其中每个推送操作之间的超时设置为 1 秒。现在,我们创建一个读取器,以使用 getReader() 函数使用流中的数据。然后,我们创建一个 readMyData() 函数,在读取器的帮助下递归地从流中读取数据。当流结束时,done 标志被设置为 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>

输出

可读流

结论

这就是 Stream API 中的可读流。它们是 Stream API 中最重要和最常用的流。几乎所有网络浏览器都支持它们,如 Chrome、Firefox、opera、edge、safari 等。现在在下一篇文章中,我们将了解 Stream API 的可写流。