Stream API - 可读流

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

Push 源 − 当您访问数据时,数据会推送给您。 您可以控制流,例如何时开始或何时暂停,甚至何时终止当前流。 例如,视频游戏流媒体。

Pull 源 − 您需要明确地向他们请求数据。 例如,借助 Fetch 或 XHR 调用访问文件。

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

可读流的工作

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

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

可读流

可读流接口

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() 构造函数的可选参数 −

底层源 − 该对象提供定义流实例行为的各种方法和属性。 方法是:start()、pull() 和 cancel(),而属性是:type 和 autoAllocateChunkSize。

排队策略 − 该对象用于定义给定流的排队策略。 它需要两个参数:highWaterMark 和 size(chunk)。

实例属性

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

Sr.No. 属性和描述
1

ReadableStream.locked

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

方法

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

Sr.No. 方法及说明
1

ReadableStream.cancel()

此方法返回一个promise ,该promise 将在流取消时解析。

2

ReadableStream.getReader()

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

3

ReadableStream.pipeThrough()

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

4

ReadableStream.pipeTo()

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

5

ReadableStream.tee()

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

ReadableStreamDefaultReader 接口

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

构造函数

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

语法

const newRead = new ReadableStreamDefaultReader(myStream)

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

实例属性

ReadableStreamDefaultReader 接口提供的属性是只读属性。 所以 ReadableStreamDefaultReader 提供的属性是 −

Sr.No. 属性和描述
1

ReadableStreamDefaultReader.closed

此属性返回一个 promise,当流因某些错误而关闭或拒绝时,该promise 将得到解决。 它允许您编写一个程序,该程序将在流处理结束时做出响应。

方法

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

Sr.No. 方法及说明
1

ReadableStreamDefaultReader.cancel()

此方法返回一个promise ,该promise 将在流取消时解析。

2

ReadableStreamDefaultReader.read()

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

3

ReadableStreamDefaultReader.releaseLock()

该方法用于解除读取器对流的锁定。

ReadableStreamDefaultController 接口

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

实例属性

Sr.No. 属性和描述
1

ReadableStreamDefaultController.desiredSize

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

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

方法

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

Sr.No. 属性和描述
1

ReadableStreamDefaultController.close()

该方法用于关闭相关流。

2

ReadableStreamDefaultController.enqueue()

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

3

ReadableStreamDefaultController.error()

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

示例 - 创建 ReadableStream

在下面的程序中,我们将使用 ReadableStream 构造函数创建一个自定义可读流。 因此,首先我们创建一个生成块数据的函数。 然后我们使用包含 start() 函数的 ReadableStream() 构造函数创建一个可读流。 此 start() 函数使用 pData() 递归函数,在控制器的帮助下将数据从 myData() 函数推送到使用者,其中每次推送操作之间的超时设置为 1 秒。 现在我们创建一个读取器来使用 getReader() 函数使用流中的数据。 然后我们创建一个 readMyData() 函数,在阅读器的帮助下递归地从流中读取数据。 当流结束时,done 标志被设置为 true,并且我们退出递归循环。

<!DOCTYPE html>
<html>
<body>
<script>
   // 为流生成数据的函数
   function* myData() {
      yield 'pink';
      yield 'blue';
      yield 'yellow';
      yield 'green';
   }
   // 使用 ReadableStream() 函数创建可读流
   const readStream = new ReadableStream({
      start(controller) {
         const data = myData();

         // 将数据添加到流中
         function pData() {
            const { done, value } = data.next();

            if (done) {
               // 如果没有更多数据可用,则关闭流
               controller.close();
               return;
            }
            // 将数据推送给消费者
            controller.enqueue(value);

            // 1秒后继续推送数据
            setTimeout(pData, 1000);
         }
         // 调用pData函数开始推送数据
         pData();
      }
   });
   // 为可读流创建一个读取器
   const myreader = readStream.getReader();
   function readMyData() {
      myreader.read().then(({ done, value }) => {
         if (done) {
            // Stream is closed
            console.log('Stream is closed');
            return;
         }
         // 处理接收到的数据
         console.log('Received data:', value);

         // 继续读取数据
         readMyData();
      });
   }
	// 调用readMyData()函数开始
    // 从可读流中读取数据
   readMyData();
</script>
</body>
</html>

输出

可读流

结论

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