Guy
Guy

Reputation: 13286

fetch response.json() and response.status

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}})

Upvotes: 67

Views: 117758

Answers (5)

Domino
Domino

Reputation: 6768

The .json method returns a promise, not the parsed value itself. If you want to access both the response and the parsed value in the same callback, you'll need to use nested functions like this:

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

Alternatively, you can use await inside an asynchronous function to eliminate the need for callbacks.

const response = await fetch(url);
const parsedValue = 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 in 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 handle(response) {
    if (response.ok) {
        return response.json().then(parsedValue => {
            // the status was ok and the body could be parsed
            return { response, parsedValue };
        }).catch(err => {
            // the status was ok but the body was empty or not JSON
            return { response };
        });

    } else {
        return response.json().catch(err => {
            // the status was not ok and the body was not JSON
            throw new Error(response.statusText);
        }).then(parsedValue => {
            // the status was not ok and the body was JSON
            throw new Error(parsedValue.error); // assuming our API returns an object with an error property
        });
    }
}

I don't think it's the best design pattern, but hopefully this clarifies how the fetch API works. Note that the call to fetch itself can throw an error if something prevents the request from being sent in the first place.

PS: I avoided naming any variable or property json since that is the name of the text format. Once it's been parsed, it is no longer JSON. You might want to use a more meaningful name than parsedValue.

Upvotes: 33

Quentin
Quentin

Reputation: 943220

The introduction of async and await makes it easy to handle data from dependant promises in one place.

Since it doesn't involve the use of callback functions, the variables all exist in the same scope.

const myFunction = async (url) => {
    const response = await fetch(url);
    const status = response.status;
    const data = await response.json();
    return { data, status };
};

Upvotes: 1

happy sharma
happy sharma

Reputation: 316

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(data.status === 200){
         // Process data here
        }else{
         // Rest of status codes (400,500,303), can be handled here appropriately
        }

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

Upvotes: 15

Suren Srapyan
Suren Srapyan

Reputation: 68645

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));

Upvotes: 134

Drag13
Drag13

Reputation: 5988

Did you try this?

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

Upvotes: 0

Related Questions