簡體   English   中英

從 ReadableStream 對象中檢索數據?

[英]Retrieve data from a ReadableStream object?

如何從ReadableStream對象獲取信息?

我正在使用 Fetch API,我沒有從文檔中看到這一點。

正文作為ReadableStream返回,我只想訪問此流中的屬性。 在瀏覽器開發工具中的 Response 下,我似乎將這些信息以 JavaScript 對象的形式組織到屬性中。

fetch('http://192.168.5.6:2000/api/car', obj)
    .then((res) => {
        if(!res.ok) {
            console.log("Failure:" + res.statusText);
            throw new Error('HTTP ' + res.status);
        } else {
            console.log("Success :" + res.statusText);
            return res.body // what gives?
        }
    })

為了從ReadableStream訪問數據,您需要調用其中一種轉換方法( 此處提供的文檔)。

舉個例子:

fetch('https://jsonplaceholder.typicode.com/posts/1')
  .then(function(response) {
    // The response is a Response instance.
    // You parse the data into a useable format using `.json()`
    return response.json();
  }).then(function(data) {
    // `data` is the parsed version of the JSON returned from the above endpoint.
    console.log(data);  // { "userId": 1, "id": 1, "title": "...", "body": "..." }
  });

編輯:如果您的數據返回類型不是 JSON 或者您不想要 JSON,則使用text()

舉個例子:

fetch('https://jsonplaceholder.typicode.com/posts/1')
  .then(function(response) {
    return response.text();
  }).then(function(data) {
    console.log(data); // this will be a string
  });

希望這有助於澄清事情。

有些人可能會發現一個async示例很有用:

var response = await fetch("https://httpbin.org/ip");
var body = await response.json(); // .json() is asynchronous and therefore must be awaited

json()將響應的主體從ReadableStream轉換為 json 對象。

await語句必須包含在async函數中,但是您可以直接在 Chrome 的控制台中運行await語句(從 62 版開始)。

res.json()返回一個承諾。 嘗試 ...

res.json().then(body => console.log(body));

聚會有點晚了,但在從使用 Sharepoint 框架的 Odata $batch 請求生成的ReadableStream中獲取有用的東西時遇到了一些問題。

與 OP 有類似的問題,但我的解決方案是使用與.json()不同的轉換方法。 在我的情況下.text()就像一個魅力。 然而,為了從文本文件中獲取一些有用的 JSON,需要進行一些操作。

請注意,您只能讀取一次流,因此在某些情況下,您可能需要克隆響應以重復讀取它:

fetch('example.json')
  .then(res=>res.clone().json())
  .then( json => console.log(json))

fetch('url_that_returns_text')
  .then(res=>res.clone().text())
  .then( text => console.log(text))

如果您只想將響應作為文本而不想將其轉換為 JSON,請使用https://developer.mozilla.org/en-US/docs/Web/API/Body/text then它來獲取承諾的實際結果:

fetch('city-market.md')
  .then(function(response) {
    response.text().then((s) => console.log(s));
  });

或者

fetch('city-market.md')
  .then(function(response) {
    return response.text();
  })
  .then(function(myText) {
    console.log(myText);
  });

我不喜歡當時的鏈接。 第二個則無法訪問狀態。 如前所述,“response.json()”返回一個承諾。 返回 '​​response.json()' 的 then 結果類似於第二次 then 的行為。 它具有在響應范圍內的額外好處。

return fetch(url, params).then(response => {
    return response.json().then(body => {
        if (response.status === 200) {
            return body
        } else {
            throw body
        }
    })
})

對於那些擁有ReadableStream並想從中獲取文本的人來說,一個簡短的技巧是將其包裝在一個新的Response (或Request )中,然后使用text方法:

let text = await new Response(yourReadableStream).text();

我從MDN 上的這個頁面得到了解決方案。 這對我有幫助。 我認為這是因為 API 返回純文本。

您可能提出了錯誤的問題來解決您的問題,但這里是您實際問題的答案。 靈感可能來自 Node.js stream/consumers模塊的源代碼。

res.body是一個ReadableStream ,它以Uint8Array的形式發出塊。 以下函數將收集單個Uint8Array中的所有塊:

export async function streamToArrayBuffer(stream: ReadableStream<Uint8Array>): Promise<Uint8Array> {
    let result = new Uint8Array(0);
    const reader = stream.getReader();
    while (true) { // eslint-disable-line no-constant-condition
        const { done, value } = await reader.read();
        if (done) {
            break;
        }

        const newResult = new Uint8Array(result.length + value.length);
        newResult.set(result);
        newResult.set(value, result.length);
    }
    return result;
}

然后,您可以使用TextDecoder將數組轉換為字符串。 然后,您可以使用JSON.parse()解析此字符串:

const buffer = await streamToArrayBuffer(res.body);
const text = new TextDecoder().decode(buffer);
const json = JSON.parse(text);

以后瀏覽器支持的時候,你也可以使用TextDecoderStream直接把流內容收集為字符串:

export async function streamToText(stream: ReadableStream<Uint8Array>): Promise<string> {
    let result = '';
    const reader = stream.pipeThrough(new TextDecoderStream()).getReader();
    while (true) { // eslint-disable-line no-constant-condition
        const { done, value } = await reader.read();
        if (done) {
            break;
        }

        result += value;
    }
    return result;
}

在閱讀下一篇文章之前,我剛剛遇到同樣的問題超過 12 個小時,以防萬一這對任何人都有幫助。 在 _api 頁面中使用 nextjs 時,您將需要使用 JSON.stringify(whole-response) 然后使用 res.send(JSON.stringify(whole-response)) 將其發送回您的頁面,並且在客戶端收到它時您需要將其翻譯回 json 格式以便它可用。 這可以通過閱讀他們的序列化部分來弄清楚。 希望能幫助到你。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM