ReadableStreamBYOBReader: read() 方法

可用性有限

此特性不是基線特性,因為它在一些最廣泛使用的瀏覽器中不起作用。

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

read() 方法是 ReadableStreamBYOBReader 介面的一個方法,用於從關聯的 可讀位元組流 中讀取資料到一個使用者提供的緩衝區檢視。如果流的內部佇列中有資料,則資料請求將從佇列中滿足。如果佇列為空,則請求可能會直接從底層位元組源進行零複製傳輸。

該方法接受一個檢視作為引數,該檢視指定了要將資料讀取到哪個緩衝區中,並返回一個 Promise。當資料可用或流被取消時,該 Promise 會以一個包含 valuedone 屬性的物件進行 fulfilled。如果流發生錯誤,Promise 會以相關的錯誤物件進行 rejected。

當提供一個數據塊時,value 屬性將包含一個新的檢視。這個檢視將與傳遞給 read() 方法的原始 view 具有相同的緩衝區/底層記憶體,並且型別也相同,只是現在填充了新的資料塊。請注意,一旦 Promise fulfilled,傳遞給方法的原始 view 將被分離,不再可用。如果流被取消,Promise 將以 value: undefined fulfilled。在這種情況下,view 的底層記憶體區域將被丟棄,不會返回給呼叫者(檢視緩衝區中所有先前讀取的資料都將丟失)。

done 屬性指示是否還期望有更多資料。如果流已關閉或被取消,則值為 true,否則為 false

該方法還有一個可選的 options.min 引數,可用於指定在流處於活動狀態時,必須有多少個元素可用後 Promise 才會 fulfilled。在 value 屬性中返回的檢視將始終至少包含此數量的元素,除非流已關閉。

語法

js
read(view)
read(view, options)

引數

view

要將資料讀取到的檢視。

options 可選

選項如下:

min

在流處於活動狀態時,在 Promise fulfilled 之前必須讀取的最少元素數量。如果未提供,Promise 將在至少讀取一個元素(最多檢視的最大尺寸)後 resolve。此數字不得大於正在讀取的檢視。

返回值

一個 Promise,它會根據流的狀態 fulfilled/rejected。結果物件包含兩個屬性:valuedone

以下是可能的情況:

  • 如果有一個數據塊可用且流仍處於活動狀態,則結果的 donefalsevalue 是一個包含新資料的檢視。這是與傳遞給 read() 方法的 view 型別相同且在同一底層記憶體上的檢視。原始 view 將被分離,不再可用。

  • 如果流已關閉,則結果的 donetruevalue 具有與上述相同的屬性。

  • 如果流被取消,則結果的 donetruevalueundefined。在這種情況下,底層記憶體將被丟棄。

  • 如果流丟擲錯誤,Promise 將以相關的錯誤 rejection。

異常

TypeError

源物件不是 ReadableStreamBYOBReader,流沒有所有者,檢視不是物件或已失效,檢視的長度為 0,options.min 為 0,或者呼叫了 ReadableStreamBYOBReader.releaseLock()(當存在待處理的讀取請求時)。

RangeError

options.min 值大於正在寫入的檢視。

示例

讀取到檢視中

這裡的示例程式碼摘自 使用可讀位元組流 中的即時示例。

首先,我們透過在流上呼叫 ReadableStream.getReader() 來建立 reader,並在選項引數中指定 mode: "byob"。我們還需要建立一個 ArrayBuffer,它是我們將要寫入的檢視的“底層記憶體”。

js
const reader = stream.getReader({ mode: "byob" });
let buffer = new ArrayBuffer(4000);

下面是一個使用 reader 的函式。該函式遞迴呼叫 read() 方法將資料讀入緩衝區。該方法接受一個 Uint8Array 型別陣列,它是原始陣列緩衝區中尚未寫入部分的一個檢視。檢視的引數是根據之前呼叫接收到的資料計算的,這些資料定義了原始陣列緩衝區的偏移量。

js
readStream(reader);

function readStream(reader) {
  let bytesReceived = 0;
  let offset = 0;

  while (offset < buffer.byteLength) {
    // read() returns a promise that fulfills when a value has been received
    reader
      .read(new Uint8Array(buffer, offset, buffer.byteLength - offset))
      .then(function processBytes({ done, value }) {
        // Result objects contain two properties:
        // done  - true if the stream has already given all its data.
        // value - some data. 'undefined' if the reader is canceled.

        if (done) {
          // There is no more data in the stream
          return;
        }

        buffer = value.buffer;
        offset += value.byteLength;
        bytesReceived += value.byteLength;

        // Read some more, and call this function again
        // Note that here we create a new view over the original buffer.
        return reader
          .read(new Uint8Array(buffer, offset, buffer.byteLength - offset))
          .then(processBytes);
      });
  }
}

當流中沒有更多資料時,read() 方法將以 done 屬性設定為 true 的物件 fulfilled,然後函式返回。

讀取最少數量的元素

此示例與上一個示例幾乎完全相同,只是我們修改了程式碼,使每次迭代讀取最少 101 個元素。

我們還將其製作成了一個即時示例。請注意,大部分程式碼與示例無關,因此被隱藏了。有關更多資訊,請參閱 使用可讀位元組流

JavaScript

js
function readStream(reader) {
  let bytesReceived = 0;
  let offset = 0;

  while (offset < buffer.byteLength) {
    // read() returns a promise that resolves when a value has been received
    reader
      .read(new Uint8Array(buffer, offset, buffer.byteLength - offset), {
        min: 101,
      })
      .then(async function processText({ done, value }) {
        // Result objects contain two properties:
        // done  - true if the stream has already given all its data.
        // value - some data. Always undefined when done is true.

        if (done) {
          logConsumer(
            `readStream() complete. Read ${value.byteLength} bytes (total: ${bytesReceived})`,
          );
          return;
        }

        buffer = value.buffer;
        offset += value.byteLength;
        bytesReceived += value.byteLength;

        // logConsumer(`Read ${bytesReceived} bytes: ${value}`);
        logConsumer(`Read ${value.byteLength} bytes (total: ${bytesReceived})`);
        result += value;

        // Read some more, and call this function again
        return reader
          .read(new Uint8Array(buffer, offset, buffer.byteLength - offset), {
            min: 101,
          })
          .then(processText);
      });
  }
}

結果

下面顯示了底層推送源(左)和消費者(右)的日誌記錄。請注意,如果瀏覽器支援 options.min 引數,那麼每次將返回至少 101 個元素(通常更多),除非流關閉。

規範

規範
Streams
# byob-reader-read

瀏覽器相容性

另見