Pobrać dane z obiektu ReadableStream?


135

Jak mogę uzyskać informacje z ReadableStreamobiektu?

Używam Fetch API i nie widzę tego w dokumentacji.

Ciało jest zwracane jako a ReadableStreami chciałbym po prostu uzyskać dostęp do właściwości w tym strumieniu. W sekcji Response w narzędziach programistycznych przeglądarki wydaje mi się, że informacje te są uporządkowane we właściwościach w postaci obiektu 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 Dzięki za odpowiedź. Próbowałem response.Body.json(), ale otrzymuję kursywę TypeError: Nie można odczytać właściwości „json” niezdefiniowanej kursywy . Czy to dlatego, że właściwość bodyUsed jest również ustawiona na wartość false? Jednak mogę wyświetlić tę treść na karcie odpowiedzi w narzędziach programistycznych przeglądarki. Jest komunikat o błędzie, który chcę odzyskać.
— noob

Więc twój problem jest związany wyłącznie z błędem 400? Co się stanie, jeśli zmienisz program obsługi na console.log(res.json());? Czy widzisz oczekiwane dane?
— Ashley 'CptLemming' Wilson

@noob Czy próbujesz odczytać odpowiedź jako strumień, jeśli res.status == 200?
— gość271314

Czy to tylko ja, czy ta dokumentacja jest po prostu błędna? Naprawiłem to jednak rozwiązaniami dotyczącymi tych odpowiedzi.
— Lucio

Odpowiedzi:


177

Aby uzyskać dostęp do danych z a ReadableStream, należy wywołać jedną z metod konwersji (dokumenty dostępne tutaj ).

Jako przykład:

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": "..." }
  });

EDYCJA: Jeśli typ zwracanych danych nie jest JSON lub nie chcesz JSON, użyjtext()

Jako przykład:

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

Mam nadzieję, że to pomoże wyjaśnić sprawę.


1
Dzięki za odpowiedzi. Próbowałem tego i nadal otrzymuję ten sam błąd, w którym res.body jest niezdefiniowany. Jestem jednak w stanie pobrać status w funkcji first then () z res.status. Wygląda na to, że tylko treść jest obiektem ReadableStream. Wydaje się, że ma zablokowaną właściwość, która jest ustawiona na true?
— noob

Gdzie próbujesz uzyskać dostęp res.body(to nie jest część mojego przykładu)? Czy możesz udostępnić przykładowy kod w swoim pierwotnym pytaniu, aby wyjaśnić, gdzie może tkwić problem.
— Ashley 'CptLemming' Wilson

1
Próbowałem uzyskać dostęp do res.body z odpowiedzi json, która została zwrócona w pierwszej funkcji .then (). Dla większej jasności dodałem próbkę do mojego pierwotnego pytania. Dzięki!
— noob

1
Niesamowite, używając natywnego reagowania i żądań i zastanawiasz się, co zrobić z ReadableStream, i to załatwiło sprawę. ++
— edencorbin

Tylko jedno ostrzeżenie, wydaje się oczywiste, ale upewnij się, że backend, w który korzystasz, faktycznie dostarcza poprawnego JSON! Zdecydowanie nie mówię z doświadczenia.
— abelito

44

Niektórym może asyncprzydać się przykład:

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

json()konwertuje treść odpowiedzi z obiektu a ReadableStreamna obiekt json.

Te awaitoświadczenia muszą być opakowane w asyncfunkcji, jednak można uruchomić awaitsprawozdań bezpośrednio w konsoli Chrome (od wersji 62).


1
Czasami prawdziwa odpowiedź dla ciebie to # 2 haha, to ma sens, dlaczego zrobiliby .json () asynchroniczną, ale nie było to od razu oczywiste
— Sanchit Batra

29

res.json()zwraca obietnicę. Próbować ...

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

3
Spróbowałem tego i wydrukowało Obietnicę zamiast jej treści.
— reectrix

Spróbuj połączyć .thenpołączenia:fetch(...).then(res => res.json()).then(data => console.log(data))
— Óscar Gómez Alcañiz

12

Trochę późno na imprezę, ale miałem problemy z uzyskaniem czegoś użytecznego z ReadableStreamwygenerowanego z żądania wsadowego Odata $ przy użyciu Sharepoint Framework.

Miał podobne problemy jak OP, ale rozwiązaniem w moim przypadku było użycie innej metody konwersji niż .json(). W moim przypadku .text()zadziałało jak urok. Konieczne były jednak pewne manipulacje, aby uzyskać przydatny kod JSON z pliku tekstowego.


2
Dziękuję Ci! To zadziałało dla mnie. Wysyłam odpowiedź http firmy Illuminate z mojego serwera Laravel za pomocą prostego return $data;. Wreszcie mogłem odczytać tę odpowiedź w przeglądarcefetch(...).then(response => response.text()).then(data => console.log(data));
— Cameron Hudson

10

Jeśli chcesz, aby odpowiedź była tylko tekstem i nie chcesz konwertować jej na JSON, użyj https://developer.mozilla.org/en-US/docs/Web/API/Body/text, a następnie then, aby uzyskać rzeczywisty wynik obietnicy:

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

lub

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

2

Nie lubię wtedy łańcuchów. Drugi nie ma wtedy dostępu do statusu. Jak wspomniano wcześniej, „response.json ()” zwraca obietnicę. Zwrócenie wyniku „response.json ()” następnie w działaniu podobnym do sekundy to. Ma dodatkową zaletę, że znajduje się w zakresie odpowiedzi.

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

Łańcuch thenpomaga odzyskać ostateczną rozstrzygniętą wartość (the body). Zagnieżdżanie ich zapobiega uzyskaniu bodywartości bez wywołania zwrotnego lub jakiegoś mechanizmu tego rodzaju. Wyobraź sobie: let body = await fetch(...).then(res => res.json()).then(data => data). To nie zadziała w zagnieżdżony sposób. Aby to sprawdzić response.status, zawsze możesz dodać throwwyjątek w pierwszym theni dodać catchdo całego łańcucha obietnic.
— Óscar Gómez Alcañiz

0

Pamiętaj, że strumień można odczytać tylko raz, więc w niektórych przypadkach może być konieczne sklonowanie odpowiedzi w celu wielokrotnego czytania:

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))
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.