fetch response.json() and response.status

55,732

Solution 1

Your status is not visible in the second then. You can just get the two properties in the single then.

json() returns a new Promise to you, so you need to create your object inside the then of the result of that function. If you return a Promise from a function, it will be fulfilled and will return the result of the fulfillment - in our case the object.

fetch("https://jsonplaceholder.typicode.com/posts/1")
.then(r =>  r.json().then(data => ({status: r.status, body: data})))
.then(obj => console.log(obj));

Solution 2

I was faced with the exact same problem last week. The .json method returns a promise to the parsed JSON, not the parsed JSON itself. If you want to access both the response and the parsed JSON at once, you'll need to use nested closures like this:

fetch(url)
    .then(response => {
        response.json().then(parsedJson => {
            // code that can access both here
        })
    });

Alternatively, you can use the async/await syntax:

async function fetchTheThing() {
    const response = await fetch(url);
    const parsedJson = await response.json();

    // code that can access both here
}

Of course, you'll want to check for errors, either with a .catch(...) call on a Promise or with a try...catch block with an async function. You could make a function that handles JSON and error cases, and then reuse it for all fetches. For example, something like this:

function fetchHandler(response) {
    if (response.ok) {
        return response.json().then(json => {
            // the status was ok and there is a json body
            return Promise.resolve({json: json, response: response});
        }).catch(err => {
            // the status was ok but there is no json body
            return Promise.resolve({response: response});
        });

    } else {
        return response.json().catch(err => {
            // the status was not ok and there is no json body
            throw new Error(response.statusText);
        }).then(json => {
            // the status was not ok but there is a json body
            throw new Error(json.error.message); // example error message returned by a REST API
        });
    }
}

I don't think it's the best design pattern, but hopefully this clarifies how the fetch API works.

Solution 3

Using two 'then's seem unnecessary to me.

async/await could get the job done pretty easily.

    fetch('http://test.com/getData')
      .then( async (response) => {

        // get json response here
        let data = await response.json();
        
        if(response.status === 200){
         // Process data here
        }else{
         // Rest of status codes (400,500,303), can be handled here appropriately
        }

      })
      .catch((err) => {
          console.log(err);
      })

Solution 4

Did you try this?

return fetch(url)
    .then((r)=> {return {response: r.json(), status: r.status}})
Share:
55,732
Guy
Author by

Guy

Updated on July 09, 2022

Comments

  • Guy
    Guy almost 2 years

    Is this the only way to use the body.json() and also get the status code?

    let status;
    
    return fetch(url)
        .then((response => {
             status = response.status;
             return response.json()
         })
        .then(response => {
            return {
                response: response,
                status: status
            }
        });
    

    This doesn't work as it returns a promise in the response field:

    .then((response)=> {return {response: response.json(), status: response.status}})
    
  • Domino
    Domino over 6 years
    response.body is a ReadableStream. response.json is a method that returns a promise to an object.
  • Guy
    Guy over 6 years
    I've tried. The problem is that r.json() is a promise and returning it like this means I get a promise in the response field.
  • Drag13
    Drag13 over 6 years
    than @Suren Srapyan is best solution I think
  • Domino
    Domino over 4 years
    Note: I have used a solution like this in production once, but it was for a small app calling a backend API I made myself. There are probably better patterns to follow if your use case isn't trivial.
  • Domino
    Domino about 4 years
    Interesting patterns can be found here: danlevy.net/you-may-not-need-axios
  • Nikhil VJ
    Nikhil VJ over 3 years
    dear lord, ajax does this so much better
  • Omiod
    Omiod over 2 years
    This is definitely the cleanest solution.
  • Stephan
    Stephan about 2 years
    @NikhilVJ Would you mind posting an equivalent ajax-only response ?