ReadableStream: tee() 方法

Baseline 已廣泛支援

此特性已相當成熟,可在許多裝置和瀏覽器版本上使用。自 ⁨2020 年 1 月⁩ 起,所有主流瀏覽器均已支援。

注意:此功能在 Web Workers 中可用。

ReadableStream 介面的 tee() 方法會 複製 當前的ReadableStream,並返回一個包含兩個新 ReadableStream 例項的二元素陣列。

這對於允許兩個讀取器順序或同時以不同速度讀取流非常有用。例如,你可能在 ServiceWorker 中這樣做,如果你想從伺服器獲取響應並將其流式傳輸到瀏覽器,同時也將其流式傳輸到 ServiceWorker 快取。由於響應體不能被消耗多次,因此你需要兩個副本才能做到這一點。

分叉(tee'd)的流會以兩個 ReadableStream 分支中較快消費者的速率部分地回壓,未讀取的資料會在較慢消費的 ReadableStream 上內部排隊,沒有限制或回壓。也就是說,當兩個分支在其內部佇列中都有未讀元素時,原始 ReadableStream 的控制器內部佇列將開始填滿,一旦其 desiredSize ≤ 0 或位元組流控制器 desiredSize ≤ 0,那麼控制器將停止呼叫傳遞給 ReadableStream() 的底層源上的 pull(controller)。如果只有一個分支被消費,那麼整個主體將被排隊到記憶體中。因此,你不應該使用內建的 tee() 來以不同速度並行讀取非常大的流。相反,請尋找一個完全回壓到較慢消費分支速度的實現。

要取消流,你需要取消兩個產生的分支。分叉流通常會在整個持續時間內鎖定它,阻止其他讀取器鎖定它。

語法

js
tee()

引數

無。

返回值

一個包含兩個 ReadableStream 例項的 Array

異常

TypeError

如果源流不是 ReadableStream,則丟擲此錯誤。

示例

在下面的簡單示例中,一個先前建立的流被分叉,然後生成的陣列的兩個成員中包含的兩個流都被傳遞給一個函式,該函式讀取兩個流中的資料並將每個流的塊順序列印到 UI 的不同部分。有關完整程式碼,請參見 簡單的分叉示例

js
function teeStream() {
  const teedOff = stream.tee();
  fetchStream(teedOff[0], list2);
  fetchStream(teedOff[1], list3);
}

function fetchStream(stream, list) {
  const reader = stream.getReader();
  let charsReceived = 0;

  // read() returns a promise that resolves
  // when a value has been received
  reader.read().then(function processText({ done, value }) {
    // Result objects contain two properties:
    // done  - true if the stream has already given you all its data.
    // value - some data. Always undefined when done is true.
    if (done) {
      console.log("Stream complete");
      return;
    }

    // value for fetch streams is a Uint8Array
    charsReceived += value.length;
    const chunk = value;
    let listItem = document.createElement("li");
    listItem.textContent = `Read ${charsReceived} characters so far. Current chunk = ${chunk}`;
    list.appendChild(listItem);

    // Read some more, and call this function again
    return reader.read().then(processText);
  });
}

規範

規範
Streams
# ref-for-rs-tee②

瀏覽器相容性

另見