Loic Duros
Loic Duros

Reputation: 5782

How to properly handle a 400 (or any non-successful status codes) with JS fetch

I have an API endpoint (which happens to be Django Rest Framework), that will usually return a response status code 201 created, but will also return a 400 error when a field hasn't been correctly entered. I'm using fetch to consume this API and return json, as follows:

export const myAPICall = (postValues) => {
    return fetch('/myapi/', someHeaders)
        .then(resp => {
            return resp.json();
        })
        .then(data => {
            return data
        }).catch(error => (error));
}

All of this is working perfectly fine, but of course a 400 error (technically a valid response, won't throw an error) and this error will have parseable JSON in it that I want to use to inform the user.

The actual response for an error may look as follows:

Response {type: "cors", url: "http://myapi/", redirected: false, status: 400, ok: false, …}

The body of the response contains useful JSON. I would still like to throw an error when the response is not ok, and so this is what I did initially:

export const myAPICall = (postValues) => {
    return fetch('/myapi/', someHeaders)
        .then(resp => {
            if (!resp.ok) {
                throw resp;
            }
            return resp.json();
        })
        .then(data => {
            return data
        }).catch(error => { throw error});
}

However, I'm struggling as to how I could just return the JSON value of the response to use later on (in a catch when calling myAPICall().then(..).catch(error => {...})

I'm actually not even sure this is the right way to do this. So if anyone has recommendation beyond just getting this as a working example, it would be most welcome. What is for sure, is I don't want to "data" returned in the then if it's an actual error since the formatting of the JSON object will be completely different.

Many thanks,

Upvotes: 4

Views: 3225

Answers (1)

rickjerrity
rickjerrity

Reputation: 814

You'd probably wanna return your own Promise and resolve/reject that promise based on the result of the fetch. Something like this probably:

export const myAPICall = (postValues) => {
  return new Promise((resolve, reject) => {
    fetch('/myapi/', someHeaders)
      .then(resp => {
        if (!resp.ok) {
          reject(resp);
        }
        else {
          resolve(resp);
        }
      })
      .catch(error => { reject(error) });
  });
}

myAPICall().then(result => console.log(result)).catch(err => console.log(err))

Upvotes: 2

Related Questions