Error Handling

Error Handling

Sicen fetch (opens in a new tab) doest not reject on http error status, manually checking and handling every request error code can be very tedious:

 
fetch("anything")
  .then(response => {
    if(!response.ok) {
      if(response.status === 404) throw new Error("Not found");
      else if(response.status === 401) throw new Error("Unauthorized");
      else if(response.status === 418) throw new Error("I'm a teapot !");
      /* ... */
      else throw new Error("Other error")
    } else {
      /* ... */
    }
  })
  .then(data => /* ... */)
  .catch(error => { /* ... */ })

Fetchtastic throws an HttpError when the response is not successful and contains helper methods to handle common codes.

We call those helper methods Error Catchers:

const api = new Fetchtastic('https://jsonplaceholder.typicode.com/posts');
 
await api
  .badRequest(error => /* 400 bad-request */)
  .unauthorized(error => /* 401 unauthorized */)
  .forbidden(error => /* 403 forbidden */)
  .notFound(error => /* 404 not-found */)
  .timeout(error => /* 408 request-timeout */)
  .serverError(error => /* 500 internal-server-error */)
  .onError(418, error => /* I'm a Teapot */)
  .resolve()
  .then(doSomethingWithResponse)
  .catch((error: Error) => {
    /* Uncaught errors */
 
    if (error instanceof HttpError) {
      console.log(error.url) // https://jsonplaceholder.typicode.com/posts
      console.log(error.status) // 429
      console.log(error.message) // Too Many Requests
    }
 
  });
 

The original config is passed along the error and can be used in order to perform an additional request, and modify the initial response:

let authToken = '';
 
const api = new Fetchtastic('https://my.backend-api.com');
 
function getResource(callback) {
  api
    .get('/resource')
    .headers({ Authorization: authToken })
    .unauthorized(async (error, config) => {
      // Renew credentials
      const credentials = await api.get('/renew-token').json();
      authToken = credentials.token;
      // Replay the original request with new credentials
      return config.headers({ Authorization: authToken }).resolve();
    })
    .json()
    .then(callback);
}

In the above example, you can notice that the execution flow is preserved as expected, .then will be called with the result of the original request or the replayed one.