fetch: inspect return value along side with json parsing

Viewed 118

This question is about how to handle promise. Example:

fetch(url)
  .then(res =>  res.json() )
  .then(data => console.log(data) )
  .catch(err => console.log("ERROR:", err.message))

My purpose is to inspect the res before pass it to json(), like:

fetch(url)
  .then(res => {
     console.log(res)        // this does not contain response body
     console.log(res.text()) //<-- how to do this
     res.json()
  })

As far as I know, text() also returns a promise, like json(). In case I also want the raw text, how to handling multiple promise at the same time?

One option might be just use text() like this:

fetch(url)
  .then(res => { res.text() })
  .then(raw => {
    let data = JSON.parse(raw) //this is no longer a promise...
    console.log(data)
  })
  .catch(err => console.log("ERROR:", err.message))

Is this a valid option, or "idiomatic" way of handling such situation? However even this is possible, I am still interested if it is possible to execute multiple promises and handle them gracefully.

1 Answers

The problem is that both res.text() and res.json() read the body of the http request from the incoming stream and once they've read it, it's gone from the stream - it can't be read again. So, you can't call one, then the other. You can only use one of them on any given request.

If you wanted to look at the data before parsing it into JSON, you'd have to get the text, keep it and then manually call JSON.parse() on the text.

So, your scheme here:

fetch(url)
  .then(res => res.text())
  .then(raw => {
    let data = JSON.parse(raw) //this is no longer a promise...
    console.log(data)
    return data;
  });

Is the general way to do that, but you would just need to add the return data so that the resolved value of the promise becomes the parsed Javascript object so whatever is trying to consume this data can have access to it.

This is the way to do what you're asking - there is no other magic preferred way.

Related