」工欲善其事,必先利其器。「—孔子《論語.錄靈公》
首頁 > 程式設計 > 為什麼 Streams API 改變了 Web 開發者的遊戲規則

為什麼 Streams API 改變了 Web 開發者的遊戲規則

發佈於2024-11-08
瀏覽:742

我们首先解释一下数据是如何通过网络发送的。它不是作为单个连续流发送的;相反,它被分成更小的块。在接收端,消费者或应用程序负责在收到所有数据后以正确的顺序和格式重新组装这些块。对于图像、视频和其他相对较大的数据类型,此过程会自动发生。

Why the Streams API is a Game-Changer for Web Developers

因此 Streams API 提供的是一种无需等待完整数据可用的方法

  1. 实时处理数据,因为它们在消费者阶段作为块接收,这在处理大量数据(如我将在本文中展示的示例)时非常有用且至关重要。
  2. 它还允许您将我们的数据视为流,当您想要发送特定类型的块时,这在后端非常有用;当您使用类似的工作人员通过网络发送大文件时,这在前端非常有用”

修订文本:“Streams API 提供的是一种在数据到达时处理数据的方法,而不是等待整个数据集可用。以下是两个主要优点:

  1. 实时数据处理:它允许您实时处理以块形式接收的数据。在处理大量数据时,例如我将在本文中讨论的示例,此功能至关重要。 (本文重点关注第一部分)
  2. 基于流的数据管理:Streams API 使您能够将数据视为连续流。这对于后端以特定块发送数据以及在前端使用 Web Worker 高效上传大文件非常有用。

我们首先将使用 Fetch API 接收数据的传统方法与新的 Streams API 方法进行比较。

使用 Fetch API 的传统方法

fetch("url") .then((response) => {
// Note that there is a middle step before we receive the final data
// Let's see what we actually receive
console.log(response.body); return response.text(); }) .then((data) => { // Perform operations with the data
});

在此示例中,response.body 是一个 ReadableStream 对象:

ReadableStream { locked: false, state: 'readable', supportsBYOB: true }

在这里,我们遇到了 Streams API 的第一个组件:ReadableStream。 ReadableStream 构造函数创建并返回一个可读的流对象,这使我们能够更有效地处理流数据。我们可以使用此构造函数来管理块中的数据,而不是等待整个数据集可用。

{ arrayBuffer(): Promise; blob(): Promise; formData(): Promise; json(): Promise; text(): Promise; }

我们需要实现一个函数来处理对象以访问实时发送的数据。这个函数应该:
1 接收 ReadableStream 作为承诺。

  1. 等待接收所有数据块。
  2. 将块合并到完整数据集中。返回完整数据作为承诺。

Why the Streams API is a Game-Changer for Web Developers

深入 ReadableStream

interface ReadableStream {
  readonly locked: boolean;
  cancel(reason?: any): Promise;
  getReader(options: { mode: "byob" }): ReadableStreamBYOBReader;
  getReader(): ReadableStreamDefaultReader;
  getReader(options?: ReadableStreamGetReaderOptions): ReadableStreamReader;
  pipeThrough(
    transform: ReadableWritablePair,
    options?: StreamPipeOptions
  ): ReadableStream;
  pipeTo(
    destination: WritableStream,
    options?: StreamPipeOptions
  ): Promise;
  tee(): [ReadableStream, ReadableStream];
}
interface ReadableStreamDefaultReader
  extends ReadableStreamGenericReader {
  read(): Promise>;
  releaseLock(): void;
}

为了处理流,我们使用 getReader() ,它返回一个 ReadableStreamDefaultReader。

下面是一个示例,我们向 Lichess.org 的 API 向某个用户请求 PGN 格式(将其视为文本)的游戏。最终结果应以文本形式显示。

fetch("https://lichess.org/api/games/user/gg").then((response) => {
  console.log(response);
  const readablestream = response.body;
  console.log(readablestream);
  const reader = readablestream.getReader();
  console.log(reader);
});

输出:

ReadableStream { locked: false, state: 'readable', supportsBYOB: true } ReadableStreamDefaultReader { stream: ReadableStream { locked: true, state: 'readable', supportsBYOB: true }, readRequests: 0, close: Promise {  } }

注意,您不能同时拥有多个读取器,因为如果 ReadableStream.locked = true, getReader() 将抛出错误,因此如果您想更改读取器,您必须首先使用 ReadableStreamDefaultReader 释放锁定。释放锁()

fetch("https://lichess.org/api/games/user/gg").then((response) => {
  const readablestream = response.body;
  console.log(readablestream);
  const reader = readablestream.getReader();
  console.log(reader);
  try {
    reader.releaseLock();
    const reader2 = readablestream.getReader(); 
// won't throw an error
    const reader3 = readablestream.getReader(); 
// will throw an error
  } catch (e) {
    console.error(e.message); 
// Invalid state: ReadableStream is locked
  }
});

现在我们在阅读器中使用 read 函数,它有两个变量

  • value:在 UintArray 中包含当前块内容,我们可以通过将每个 int 转换为 char 并合并或简单地使用 TextDecoder().decode() 将其转换为字符串
let string = result.push(
  value.reduce((p, c) => {
    return p   c.fromCharCode();
  }, "")
); // or
let string = new TextDecoder().decode(value); 
// both achieve the same thing converting Uint8Array to string

完整代码示例

  • 这是处理流和合并块的完整示例:
fetch("https://lichess.org/api/games/user/gg")
  .then((response) => {
    return new Promise((resolve, reject) => {
      const readablestream = response.body;
      const reader = readablestream.getReader();
      let result = [];
      reader.read().then(function handlechunks({ done, value }) {
        if (done) {
          resolve(result);
          return;
        }
        const pgn = new TextDecoder().decode(value);
        result.push(pgn);
        reader.read().then(handlechunks);
      });
    });
  })
  .then((result) => {
    console.log(result);
  });
// console.log(value)
Uint8Array(551) [
     91,  69, 118, 101, 110, 116,  32,  34,  82,  97, 116, 101,
    100,  32,  98, 108, 105, 116, 122,  32, 103,  97, 109, 101,
     34,  93,  10,  91,  83, 105, 116, 101,  32,  34, 104, 116,
    116, 112, 115,  58,  47,  47, 108, 105,  99, 104, 101, 115,
    115,  46, 111, 114, 103,  47,  90, 122,  78,  66,  90, 119,
    100,  71,  34,  93,  10,  91,  68,  97, 116, 101,  32,  34,
     50,  48,  50,  48,  46,  48,  49,  46,  49,  48,  34,  93,
     10,  91,  87, 104, 105, 116, 101,  32,  34,  86, 101, 101,
    118, 101, 101,  50,
    ... 451 more items
  ]
// console.log(new TextDecoder().decode(value))
[Event "Rated blitz game"]
[Site "https://lichess.org/ZzNBZwdG"]
[Date "2020.01.10"]
[White "Veevee222"]
[Black "gg"]
[Result "0-1"]
[UTCDate "2020.01.10"]
[UTCTime "20:21:02"]
[WhiteElo "1858"]
[BlackElo "1863"]
[WhiteRatingDiff "-6"]
[BlackRatingDiff " 35"]
[Variant "Standard"]
[TimeControl "180 0"]
[ECO "C00"]
[Termination "Normal"]
1. e4 e6 2. d4 d6 3. c4 Nf6 4. Nc3 c5 5. f4 cxd4 6. Qxd4 Nc6 7. Qd1 b6 8. g3 Bb7 9. Bg2 Rc8 10. Nf3 Be7 11. O-O O-O 12. b3 Nb4 13. Bb2 a5 14. Re1 Qc7 15. a3 Na6 16. Rc1 Nc5 17. Qd4 Nxb3 18. Qd1 Nxc1 19. e5 0-1

例如链接

例如完整代码go

Why the Streams API is a Game-Changer for Web Developers

现在,我们可以在游戏通过网络发送的 PGN 时逐步访问它们。例如,如果我们在网站 UI 中使用已加载的游戏,则用户无需在空白或加载屏幕前等待,直到所有游戏都加载完毕。相反,数据可以逐步显示,从用户体验的角度来看,这要好得多。
例如完整的代码在这里

版本聲明 本文轉載於:https://dev.to/anasmustafa123/why-the-streams-api-is-a-game-changer-for-web-developers-1030?1如有侵犯,請洽[email protected]刪除
最新教學 更多>

免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。

Copyright© 2022 湘ICP备2022001581号-3