如何从ReadableStream对象中获取信息?

我使用的取回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?
        }
    })

当前回答

有点晚了,但是在使用Sharepoint框架从Odata $batch请求生成的ReadableStream中获得一些有用的东西时遇到了一些问题。

与OP有类似的问题,但在我的情况下,解决方案是使用不同于.json()的转换方法。在我的例子中,.text()就像一个魅力。然而,为了从文本文件中获得一些有用的JSON,需要进行一些修改。

其他回答

为了从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
  });

你可能问了一个错误的问题来解决你的问题,但这里有一个对你实际问题的答案。灵感可能来自Node.js流/消费者模块的源代码。

body是一个ReadableStream,它以Uint8Arrays的形式发出chunk。下面的函数将收集单个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);
        result = newResult;
    }
    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;
}

response.json()返回一个Promise。试一试……

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

其中response是fetch(…)的结果

有些人可能会发现一个异步的例子很有用:

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语句必须被包装在一个异步函数中,但是你可以直接在Chrome的控制台上运行await语句(从版本62开始)。

有点晚了,但是在使用Sharepoint框架从Odata $batch请求生成的ReadableStream中获得一些有用的东西时遇到了一些问题。

与OP有类似的问题,但在我的情况下,解决方案是使用不同于.json()的转换方法。在我的例子中,.text()就像一个魅力。然而,为了从文本文件中获得一些有用的JSON,需要进行一些修改。