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.