Efficient data handling with the Streams API title.  A vibrant gradient with a JavaScript logo in the bottom-left corner and a graphic representing data being processed in a browser in the top-right corner.
贊助

使用 Streams API 高效處理資料

閱讀時間 6 分鐘

Streams API 使您能夠訪問透過網路接收的資料流,並在網頁上使用 JavaScript 進行處理。以前,如果您想處理透過網路獲取的資料,您必須先下載整個資源,等待其轉換為您可以處理的格式,然後再開始處理。使用 Streams API,您可以在原始資料到達時使用 JavaScript 進行處理,這使其非常適合處理連續資料來源、即時轉換資料、在收到所需資料時取消流等等。

在本文中,我們將探討 Streams API 的概念、用法和實際應用。我們還將透過一個實際示例,構建一個小應用程式,該應用程式使用該 API 來轉換資料流。

理解 Streams API

Streams API 提供了一種在 JavaScript 中處理流式資料的標準方法。它允許您逐塊處理資料,對於處理 Web 應用程式中的大型資源或即時資料非常高效。您應該瞭解 Streams API 中的這些關鍵概念:

資料塊 (Chunks)

資料以稱為資料塊的片段順序讀取。一個數據塊可以是一個位元組,也可以是較大的內容,例如特定大小的 型別化陣列。單個流可以包含不同大小和型別的資料塊。

背壓

API 自動管理背壓,確保快速生產者不會壓倒慢速消費者。這透過內部佇列機制來處理。

管道 (Piping)

API 提供諸如 pipeThrough()pipeTo() 之類的方法來連線流,從而允許對資料進行鏈式處理。

API 包含以下針對不同型別流的抽象:

ReadableStream

表示可以從中讀取資料的源。它可以從各種源建立,例如 fetch 響應或檔案輸入。

WritableStream

表示可以向其中寫入資料的目標。可用於寫入檔案或將資料傳送到伺服器等任務。

TransformStream

允許在資料從可讀流傳遞到可寫流時修改資料。適用於壓縮或加密等任務。

構建 Node.js 應用程式

首先,請按照我們上一篇文章 在 Vultr 上部署伺服器 部分所述的步驟部署伺服器。接下來,透過 SSH 訪問伺服器終端,併為我們的 Web 應用程式設定專案。

我們將使用 Nano 文字編輯器在伺服器上建立和編輯我們的專案檔案。您可以在 快捷鍵備忘單 中查詢使用 Nano 的幫助。我們還將使用 Uncomplicated Firewall (UFW) 來控制允許進出伺服器的流量。在我們的應用程式中,Node.js 服務於應用程式的索引,並使用 http-server 執行應用程式。像 Python 和 Apache 這樣的伺服器也可以達到類似的效果。我們使用 UFW 啟用埠 8000 的入站流量。

  1. 建立一個專案目錄,並進入該目錄。

    bash
    mkdir streaming-app && cd streaming-app
    
  2. 初始化一個 Node.js 專案。

    bash
    npm init -y
    
  3. 安裝 HTTP 伺服器。

    bash
    npm install http-server
    
  4. 建立一個 HTML 檔案。

    bash
    nano index.html
    
  5. 將以下程式碼複製並貼上到 index.html 檔案中。

    html
    <!doctype html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>File Stream Transformer</title>
      </head>
      <body>
        <h1>File Stream Transformer</h1>
        <button id="loadFileButton">Load and Transform File</button>
        <br />
        <h2>Transformed Content:</h2>
        <pre id="outputText"></pre>
    
        <script src="app.js"></script>
      </body>
    </html>
    
  6. 儲存並退出檔案。

  7. 在專案目錄中建立一個文字檔案 textfile.txt,並提供一些示例文字。您可以方便地使用 此文字檔案 中的內容。

建立示例 Streams API 應用

  1. 在 streaming-app 目錄中,建立一個 JavaScript 檔案。

    bash
    nano app.js
    
  2. 將以下 JavaScript 程式碼複製並貼上到 app.js 中。

    js
    document.addEventListener("DOMContentLoaded", initializeApp);
    
    function initializeApp() {
      const loadFileButton = document.getElementById("loadFileButton");
      const outputText = document.getElementById("outputText");
    
      loadFileButton.addEventListener("click", () =>
        fetchAndTransformFile(outputText),
      );
    }
    
    async function fetchAndTransformFile(outputElement) {
      clearOutput(outputElement);
    
      try {
        const response = await fetch("textfile.txt");
        const readableStream = response.body;
        const transformStream = createTransformStream();
        const writableStream = createWritableStream(outputElement);
    
        await readableStream.pipeThrough(transformStream).pipeTo(writableStream);
    
        console.log("File stream processing completed");
      } catch (error) {
        handleError(error, outputElement);
      }
    }
    
    function createTransformStream() {
      return new TransformStream({
        transform(chunk, controller) {
          const text = new TextDecoder().decode(chunk);
          const upperCaseChunk = text.toUpperCase();
          controller.enqueue(new TextEncoder().encode(upperCaseChunk));
        },
      });
    }
    
    function createWritableStream(outputElement) {
      return new WritableStream({
        write(chunk) {
          const text = new TextDecoder().decode(chunk);
          outputElement.textContent += text;
        },
      });
    }
    
    function clearOutput(outputElement) {
      outputElement.textContent = "";
      outputElement.style.color = "black";
    }
    
    function handleError(error, outputElement) {
      console.error("Error during stream processing:", error);
      outputElement.textContent = `An error occurred: ${error.message}`;
      outputElement.style.color = "red";
    }
    
  3. 儲存並退出檔案。

  4. 允許連線到埠 8080。

    bash
    ufw allow 8080
    
  5. 啟動檔案伺服器。

    bash
    npx http-server
    
  6. 訪問應用程式 URL http://<server-ip>:8080,然後點選 載入並轉換 按鈕。您將看到整個文字檔案被獲取並轉換為大寫字元。

當點選 載入並轉換 按鈕時,fetchAndTransformFile() 函式從伺服器的檔案系統中獲取 textfile.txt。伺服器以 ReadableStream 的形式響應資料,這使得檔案可以分塊處理。在客戶端,這個 ReadableStream 透過一個 TransformStream 進行管道傳輸,該流將每個文字塊轉換為大寫。然後,轉換後的資料塊透過 WritableStream 進行管道傳輸,該流將結果文字附加到 HTML 元素以進行顯示。這表明了 Streams API 如何用於獲取檔案,以及在瀏覽器獲取資料時對其進行處理、轉換和顯示,而不是在記憶體中對整個檔案執行操作。

實際用例和示例

  1. 在影片流平臺中
    • 用例:高效處理和傳輸大型影片檔案。
    • 示例:影片流服務可以使用 Streams API 將大型影片檔案分解成更小的塊,進行處理(例如,應用濾鏡或壓縮),然後逐步傳輸給使用者。這可以實現更流暢的播放並減少初始載入時間。
  2. 在資料視覺化應用程式中
    • 用例:即時處理和視覺化大型資料集或連續資料流。
    • 示例:金融儀表板可以使用 Streams API 即時處理市場資料。隨著新資料的到來,它可以被轉換、過濾並立即顯示在圖表或圖形上,從而實現即時更新,而不會壓垮瀏覽器的資源。
  3. 在檔案上傳/下載系統中
    • 用例:處理帶有進度跟蹤和即時處理的大檔案傳輸。
    • 示例:雲端儲存服務可以使用 Streams API 上傳大檔案。檔案可以作為流讀取,即時壓縮或加密,並分塊傳送到伺服器。這使得能夠進行進度跟蹤、暫停和恢復傳輸,並高效地利用記憶體,特別是對於非常大的檔案。

總結

在本文中,我們深入探討了 Streams API 的概念、用法和實際實現。我們開發了一個基本應用程式,演示瞭如何使用 Streams API 獲取和轉換資料。透過這個實踐示例,我們學習瞭如何讀取、寫入和操作資料流。我們希望這將激發您建立高效、響應迅速的現代 Web 應用程式。

學習此 API 的一些好的後續步驟是執行更復雜的處理。您可以檢視 MDN Streams API 示例之一,它與此專案非常相似,但它手動迴圈資料塊,並在每個新資料塊到達時將其記錄到控制檯。其他的 示例 展示了使用此 API 的不同方法,而 取消 fetch 演示則展示了當客戶端收到所需資料時如何停止進行中的網路操作。

這是一篇由 Vultr 贊助的文章。Vultr 是全球最大的私營雲計算平臺。Vultr 是開發者的首選,已為 185 個國家/地區的 150 萬多客戶提供了靈活、可擴充套件、全球化的雲計算、雲 GPU、裸金屬和雲端儲存解決方案。瞭解更多關於 Vultr 的資訊。