RuF
RuF

Reputation: 558

How to handle error status in ES6 Promises?

I am using ES6 and trying to handle error status of the fetch() result.

I know I can catch error like this:

fetch(`http://${this.serverAddress}/reset`)
        .then((resp) => {
            Logger.debug(JSON.stringify(resp));
        })
        .catch((err) => {
            Logger.debug(JSON.stringify(err));
        });

In catch block I take an Error with message "Failed to fetch". There is no status information.

I have found the following suggestion:

fetch('/some/url/')
  .then(processResponse)
  .then(response => {
    // do something
  })
  .catch(response => {
    // repsonses with status >= 400 get rejected. you can access response.status and response.data here too
    if (response.status === 400) {
        // handle form validation errors, response.data.errors...
    } else if (response.status === 403) {
        // handle permission errors
    } // etc
  });

But response.status is undefined in catch block.

How can I get status code of the error to handle it?

UPDATE:

Thank you for the responces. Please see my updates:

My actual token looks as http://api.service/v2/prices/latest?token=err. If I write my token instead of err, then it works. When I try this URL, my code go to the catch block, not then.

I noticed the following error in browser console:

No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access. The response had HTTP status code 401. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

If I add {mode: "no-cors"}, code go to the then, but status is always 0. This is not that I want.

I tried to add

mode: "cors",
headers: {
        "Access-Control-Allow-Credentials": true,
        "Access-Control-Allow-Origin": "*",
        "Content-Type": "application/json"
    }

This is not help, I still have No 'Access-Control-Allow-Origin' header error.

Upvotes: 0

Views: 1081

Answers (4)

Bee
Bee

Reputation: 1296

As seen in the docs the catch block will be reached only if the request didn't complete. When there is a status code available (and all the other data is received as well) fetch will resolve and therefore the then block will be reached.

The Promise returned from fetch() won’t reject on HTTP error status even if the response is an HTTP 404 or 500. Instead, it will resolve normally (with ok status set to false), and it will only reject on network failure or if anything prevented the request from completing. - Source

So all you have to do is logging resp.status instead of resp.

fetch(`http://${this.serverAddress}/reset`)
  .then((resp) => {
    Logger.debug(JSON.stringify(resp.status));
  })
  .catch((err) => {
    Logger.debug(JSON.stringify(err));
});

In catch block I take an Error with message "Failed to fetch". There is no status information.

So in case the catch block is getting called the request didn't even finish. This might be caused because you are not using options like method, headers,... If needed, which one and what values depends on the backend you are using.

Upvotes: 0

himank
himank

Reputation: 439

After the fetch request check if response is as expected. If not, throw new error with a custom message. In the catch check if this custom message is there for the thrown error. Handle accordingly. You can also create custom Errors and check the same.

Upvotes: 0

dhilt
dhilt

Reputation: 20734

You may try to handle the error status by throwing error during response processing right after the fetch is done with !ok:

fetch('/some/url/')
  .then(response => {
    if (!response.ok) {
      throw Error({ status: response.status });
    }
    response.json();
  })
  .then(response => {
    // do something
  })
  .catch(error => {
    switch(error.status) {
      // ...
    }
  });

Upvotes: 1

Vladu Ionut
Vladu Ionut

Reputation: 8183

You can't check the status in code.

The Promise returned from fetch() won’t reject on HTTP error status even if the response is an HTTP 404 or 500. Instead, it will resolve normally (with ok status set to false), and it will only reject on network failure or if anything prevented the request from completing.

Basically, fetch() will only reject a promise if a networking error occurs.

The fetch API provides a simple ok flag that indicates whether an HTTP response’s status code is in the successful range or not. See the below example

fetch("http://httpstat.us/500")
    .then(function(res) {
        if (!res.ok) {
            throw Error(res.statusText);
        }
        return res;
    }).then(function(res) {
        console.log("ok");
    }).catch(function(error) {
        console.log(error);
    });

Upvotes: 0

Related Questions