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();
    })
Nowicjusz
źródło
5
Dokumentacja Body API
Francesco Pezzella
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ę.

Ashley „CptLemming” Wilson
źródło
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).

kolęda
źródło
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));
pinoyyid
źródło
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.

Dan Mehlqvist
źródło
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);
  });
AlexChaffee
źródło
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
        }
    })
})
Mardok
źródło
Ł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))
Chris Halcrow
źródło