Retrieve data from a ReadableStream object?

233,779

Solution 1

In order to access the data from a ReadableStream you need to call one of the conversion methods (docs available here).

As an example:

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

EDIT: If your data return type is not JSON or you don't want JSON then use text()

As an example:

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

Hope this helps clear things up.

Solution 2

Some people may find an async example useful:

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

json() converts the response's body from a ReadableStream to a json object.

The await statements must be wrapped in an async function, however you can run await statements directly in the console of Chrome (as of version 62).

Solution 3

res.json() returns a promise. Try ...

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

Solution 4

Little bit late to the party but had some problems with getting something useful out from a ReadableStream produced from a Odata $batch request using the Sharepoint Framework.

Had similar issues as OP, but the solution in my case was to use a different conversion method than .json(). In my case .text() worked like a charm. Some fiddling was however necessary to get some useful JSON from the textfile.

Solution 5

Note that you can only read a stream once, so in some cases, you may need to clone the response in order to repeatedly read it:

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))
Share:
233,779

Related videos on Youtube

noob
Author by

noob

Updated on July 08, 2022

Comments

  • noob
    noob almost 2 years

    How may I get information from a ReadableStream object?

    I am using the Fetch API and I don't see this to be clear from the documentation.

    The body is being returned as a ReadableStream and I would simply like to access a property within this stream. Under Response in the browser dev tools, I appear to have this information organised into properties, in the form of a JavaScript object.

    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();
        })
    
    • noob
      noob over 7 years
      @FrancescoPezzella Thanks for the response. I have tried response.Body.json() , but I am getting italic TypeError: Cannot read property 'json' of undefined italic . Is this because the bodyUsed property is also set to false? However I can view this body under the response tab in browser developer tools. There is an error message which I'd like to retrieve.
    • Ashley 'CptLemming' Wilson
      Ashley 'CptLemming' Wilson over 7 years
      So your issue is purely related to the error 400 condition? What happens if you change the handler to console.log(res.json());? Do you see the data you are expecting?
    • guest271314
      guest271314 over 7 years
      @noob Are you trying to read the response as a stream if res.status == 200?
    • Lucio
      Lucio almost 6 years
      Is it just me or that documentation is plain wrong? I did fix it with the solutions on this answers though.
    • xaddict
      xaddict over 3 years
      I know it has been a while but for the sake of keeping stackoverflow great, please just accept the right answer. The one with over 200 upvotes.
  • noob
    noob over 7 years
    Thanks for the response. I have tried this and am still getting the same error where res.body is undefined. I am able to retrieve the status however in first then() function with res.status. It seems that only the body is a ReadableStream object. It does seem to have a property locked, which is set to true?
  • Ashley 'CptLemming' Wilson
    Ashley 'CptLemming' Wilson over 7 years
    Where are you trying to access res.body (this isn't part of my example)? Can you share some sample code in your original question to make it clearer where your problem might be.
  • noob
    noob over 7 years
    I tried accessing res.body from the json response that was returned in first .then() function. I have added a sample to my original question for more clarity. Thanks!
  • edencorbin
    edencorbin over 7 years
    Awesome, using react and request native, and wondering what in the world to do with a ReadableStream, and this did the trick. ++
  • reectrix
    reectrix over 6 years
    I tried this, and it printed out the Promise instead of the body.
  • Cameron Hudson
    Cameron Hudson almost 6 years
    Thank you! This worked for me. I am sending an Illuminate http response from my Laravel server with a simple return $data;. I was finally able to read this response in the browser with fetch(...).then(response => response.text()).then(data => console.log(data));
  • abelito
    abelito about 5 years
    Just a headsup, seems like a no-brainer, but make sure the backend you're hitting is actually providing valid JSON! Definitely not speaking from experience.
  • Óscar Gómez Alcañiz
    Óscar Gómez Alcañiz almost 5 years
    Try to chain the .then calls: fetch(...).then(res => res.json()).then(data => console.log(data))
  • Óscar Gómez Alcañiz
    Óscar Gómez Alcañiz almost 5 years
    The chaining then helps you retrieve the final resolved value (the body). Nesting them prevents you from being able to get the body value without a callback or some mechanism of the sort. Imagine this: let body = await fetch(...).then(res => res.json()).then(data => data). This wouldn't work in the nested way. To check for response.status you can always throw an exception inside the first then, and add a catch to the whole promise chain.
  • Azurespot
    Azurespot over 4 years
    What if the response of the ReadableStream is an image?
  • Stefan Rein
    Stefan Rein over 4 years
    @Azurespot It depends on what you want to do with the Image. You could call one of these methods developer.mozilla.org/en-US/docs/Web/API/Body, for example const imageBlob = await response.blob(); and then const objectUrl = URL.createObjectURL(imageBlob); htmlImageElement.src = objectUrl;. The returned URL is released automatically when the document is unloaded. But if your page has dynamic use, you should release it explicitly by calling window.URL.revokeObjectURL(objectUrl). Or use a FileReader.
  • Sanchit Batra
    Sanchit Batra almost 4 years
    Sometimes the real answer for you really is #2 haha, it makes sense why they'd make .json() asynchronous but it wasn't immediately obvious
  • Nash Worth
    Nash Worth over 3 years
    AGREE. Preferred in enterprise environment. : )
  • lumayara
    lumayara over 3 years
    This helped me so much! Thank you!
  • PhilosophOtter
    PhilosophOtter over 3 years
    thank you so so so much for this resposne! I was bashing my face against everything not understanding all this "readable stream" api documentation and its all about chunks & text files and crap im not using. this worked! I haven't done backend work in over a year so i'm so rusty, this looks like what I used to learn/write and I knew I was forgetting something like this - this was it!
  • KyleMit
    KyleMit about 3 years
    Yay for CityMarket.md <3
  • Alex W
    Alex W over 2 years
  • Dan Barron
    Dan Barron about 2 years
    This worked for me and is so simple. Thanks!