zolamk
zolamk

Reputation: 6357

Fetch API Global Error Handler

I am using the fetch API with a REST API, and i want to handle certain errors globally, errors like 500, 503 ... I tried doing something like this

function(url, method, data) {
    return fetch(url, {
        method: method || "GET",
        body: JSON.stringify(data),
        mode: "cors",
        headers: {
        "Content-Type": "application/json; charset=utf-8"
        }
    }).then(response => {

        if (response.ok && response.status < 500) console.log("ouch");;

        return response;

});

but it doesn't seem to be working. how do i catch 500, 503 ... in the fetch api?

Upvotes: 8

Views: 9171

Answers (2)

Rehan Haider
Rehan Haider

Reputation: 1061

You can try the following approach, by using it you can handle all possible errors in one place and generate a custom response to return e.g. if all requests return JSON data then you can convert the response to JSON before returning it.

function secureFetch(url, method, data) {
  return new Promise((resolve, reject) => {
    fetch(url, {
        method: method || "GET",
        body: JSON.stringify(data),
        mode: "cors",
        headers: {
          "Content-Type": "application/json; charset=utf-8"
        }
      }).then(response => {
        // response only can be ok in range of 2XX
        if (response.ok) {
          // you can call response.json() here too if you want to return json
          resolve(response);
        } else {
          //handle errors in the way you want to
          switch (response.status) {
            case 404:
              console.log('Object not found');
              break;
            case 500:
              console.log('Internal server error');
              break;
            default:
              console.log('Some error occured');
              break;
          }

          //here you also can thorow custom error too
          reject(response);
        }
      })
      .catch(error => {
        //it will be invoked mostly for network errors
        //do what ever you want to do with error here
        console.log(error);
        reject(error);
      });
  });
}

secureFetch('https://jsonplaceholder.typicode.com/posts/1')
  .then(response => response.json())
  .then(json => console.log(json))
  .catch(error => console.log(error));

secureFetch('https://jsonplaceholder.typicode.com/posts/100000000')
  .then(response => response.json())
  .then(json => console.log(json))
  .catch(error => console.log(error));

Update: You can achieve the same result without creating an extra promise

function secureFetch(url, method, data) {
  return fetch(url, {
    method: method || "GET",
    body: JSON.stringify(data),
    mode: "cors",
    headers: {
      "Content-Type": "application/json; charset=utf-8"
    }
  }).then(response => {
    // Server returned a status code of 2XX
    if (response.ok) {
      // you can call response.json() here if you want to return the json
      return response;
    }

    // Server returned a status code of 4XX or 5XX
    // Throw the response to handle it in the next catch block
    throw response;
  }).catch(error => {
    // It will be invoked for network errors and errors thrown from the then block
    // Do what ever you want to do with error here
    if (error instanceof Response) {
      // Handle error according to the status code
      switch (error.status) {
        case 404:
          // You can also call global notification service here
          // to show a notification to the user
          // notificationService.information('Object not found');
          console.log('Object not found');
          break;
        case 500:
          console.log('Internal server error');
          break;
        default:
          console.log('Some error occurred');
          break;
      }
    } else {
      // Handle network errors
      console.log('Network error');
      console.log(error);
    }
    // In case you don't want to throw the error just return some value here
    // This will be returned to the then block as a resolved promise
    // return { success: false };

    // Here you can throw a custom error too
    // throw new Error('Something went wrong');
    throw error;
  });
}


secureFetch('https://jsonplaceholder.typicode.com/posts/1')
  .then(response => response.json())
  .then(json => console.log(json))
  .catch(error => console.log(error));

secureFetch('https://jsonplaceholder.typicode.com/posts/100000000')
  .then(response => response.json())
  .then(json => console.log(json))
  .catch(error => console.log(error));

Upvotes: 15

Abhishek
Abhishek

Reputation: 380

Here you can handle with promise something like this:

function status(response) {
    /*You can handle status here.*/
    if (response.status >= 200 && response.status < 300) {
      return Promise.resolve(response)
    } else {
      return Promise.reject(new Error(response.statusText))
    }
  }

  function json(response) {
    return response.json()
  }
function makeCall(url, method, data) {
    return fetch(url, {
        method: method || "GET",
        body: JSON.stringify(data),
        mode: "cors",
        headers: {
        "Content-Type": "application/json; charset=utf-8"
        }
    })
    .then(status)
    .then(json)
    .then(function(data) {
    	console.log('Request succeeded with JSON response', data);
    }).catch(function(error) {
      console.log('Request failed', error);
    });
}

var url = 'http://localhost:4200/profile';
var data = {username: 'example'};
makeCall(url, 'POST', data);

Upvotes: -2

Related Questions