Получить данные из объекта ReadableStream?


136

Как я могу получить информацию от ReadableStreamобъекта?

Я использую Fetch API и не вижу, чтобы это было ясно из документации.

Тело возвращается как объект, ReadableStreamи я просто хотел бы получить доступ к свойству в этом потоке. В разделе «Ответ» в инструментах разработчика браузера я, кажется, организовал эту информацию в свойствах в форме объекта JavaScript.

fetch('http://192.168.5.6:2000/api/car', obj)
    .then((res) => {
        if(res.status == 200) {
            console.log("Success :" + res.statusText);   //works just fine
        }
        else if(res.status == 400) {
            console.log(JSON.stringify(res.body.json());  //res.body is undefined.
        }

        return res.json();
    })


2
@FrancescoPezzella Спасибо за ответ. Я пробовал response.Body.json(), но получаю курсив TypeError: невозможно прочитать свойство json с неопределенным курсивом . Это потому, что для свойства bodyUsed также установлено значение false? Однако я могу просмотреть это тело на вкладке ответа в инструментах разработчика браузера. Появляется сообщение об ошибке, которое я хотел бы получить.
— noob

Итак, ваша проблема связана исключительно с ошибкой 400? Что произойдет, если вы измените обработчик на console.log(res.json());? Вы видите ожидаемые данные?
— Эшли 'CptLemming' Уилсон

@noob Вы пытаетесь прочитать ответ как поток, если res.status == 200?
— guest271314

Это только я или эта документация явно неверна? Я исправил это с помощью решений по этим ответам.
— Lucio

Ответы:


178

Чтобы получить доступ к данным из файла, 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
  });

Надеюсь, это поможет прояснить ситуацию.


1
Спасибо за ответ. Я пробовал это и все еще получаю ту же ошибку, когда res.body не определен. Однако я могу получить статус сначала в функции then () с res.status. Кажется, что объектом ReadableStream является только тело. Кажется, что свойство заблокировано, для которого установлено значение true?
— noob

Куда вы пытаетесь получить доступ res.body(это не часть моего примера)? Не могли бы вы поделиться образцом кода в исходном вопросе, чтобы было понятнее, где может быть ваша проблема.
— Эшли 'CptLemming' Уилсон

1
Я попытался получить доступ к res.body из ответа json, который был возвращен в первой функции .then (). Я добавил образец к своему исходному вопросу для большей ясности. Спасибо!
— noob

1
Потрясающе, используя реагирование и нативные запросы, и задаваясь вопросом, что вообще делать с ReadableStream, и это помогло. ++
— edencorbin

Просто напомню, что кажется несложным, но убедитесь, что сервер, на который вы обращаетесь, действительно предоставляет действительный JSON! Определенно не по опыту.
— abelito

45

Некоторым может asyncпригодиться пример:

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

json()преобразует тело ответа из объекта ReadableStreamjson.

Эти awaitзаявления должны быть завернуты в asyncфункции, однако вы можете запустить awaitзаявления непосредственно в консоли Chrome (в версии 62).


1
Иногда настоящий ответ для вас - №2, ха-ха, имеет смысл, почему они сделали .json () асинхронным, но это было не сразу очевидно
— Санчит Батра

29

res.json()возвращает обещание. Пытаться ...

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

3
Я попробовал это, и он распечатал обещание вместо тела.
— reectrix

Попробуйте .thenfetch(...).then(res => res.json()).then(data => console.log(data))
— Оскар Гомес Альканьис

12

Немного опоздал на вечеринку, но возникли проблемы с получением чего-то полезного из ReadableStreamпакетного запроса, созданного с помощью Odata $, с использованием Sharepoint Framework.

Были проблемы, аналогичные OP, но решение в моем случае заключалось в использовании другого метода преобразования, чем .json(). В моем случае .text()сработало как шарм. Однако, чтобы получить полезный JSON из текстового файла, потребовалось немного возиться.


2
Спасибо! Это сработало для меня. Я отправляю HTTP-ответ Illuminate с моего сервера Laravel с простым return $data;. Я наконец смог прочитать этот ответ в браузере сfetch(...).then(response => response.text()).then(data => console.log(data));
— Кэмерон Хадсон

10

Если вы просто хотите получить ответ в виде текста и не хотите преобразовывать его в 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);
  });

2

Мне не нравятся цепочки. Второй тогда не имеет доступа к статусу. Как было сказано ранее, response.json () возвращает обещание. Возврат тогда результата response.json () в a действует аналогично секунде then. У него есть дополнительный бонус, заключающийся в том, что он находится в рамках ответа.

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

Цепочка thenпомогает вам получить окончательное разрешенное значение ( body). Их вложение не дает вам получить bodyзначение без обратного вызова или какого-либо механизма подобного рода. Представьте себе , это: let body = await fetch(...).then(res => res.json()).then(data => data). Это не будет работать вложенным способом. Чтобы проверить, response.statusвы всегда можете throwсоздать исключение внутри первого thenи добавить catchко всей цепочке обещаний.
— Оскар Гомес Альканьис

0

Обратите внимание, что вы можете прочитать поток только один раз, поэтому в некоторых случаях вам может потребоваться клонировать ответ, чтобы повторно читать его:

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))
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.