Axios interceptor
Let's create an axios instance that retries the network call upon failure.
Import the package and create an axios instance.
const axios = require("axios");
const instance = axios.create();
Let's add functions that execute during lifecycle of network call. .use
takes two functions as argument. First function is executed on success, and second one is error handler.
instance.interceptors.request.use(
function (config) {
config.metadata = { startTime: new Date() };
return config;
},
function (error) {
return Promise.reject(error);
}
);
instance.interceptors.response.use(
function (response) {
response.config.metadata.endTime = new Date();
response.duration =
response.config.metadata.endTime -
response.config.metadata.startTime;
return response;
},
function (error) {
try {
const { config } = error;
// if config or retry option is not available, then return the error object
if (!config || !config.retry) return Promise.reject(error);
// Set the variable for keeping track of the retry count
config._retryCount = config._retryCount || 0;
// Check if we've maxed out the total number of retries
if (config._retryCount >= config.retry) {
// Reject with the error
return Promise.reject(error);
}
// Increase the retry count
config._retryCount += 1;
const timeOutError = error.code === "ECONNABORTED";
const notFoundError = error.code === "ENOTFOUND";
const connectionResetError = error.code === "ECONNRESET";
const { status = "" } = error.response || {};
const statusString = status.toString();
const error_4xx = statusString.startsWith("4");
const error_5xx = statusString.startsWith("5");
const should_retry =
timeOutError ||
notFoundError ||
connectionResetError ||
error_4xx ||
error_5xx;
console.log(`[error.code]`, error.code);
console.log(`[error_4xx]`, error_4xx);
console.log(`[error_5xx]`, error_5xx);
console.log(`[should_retry]`, should_retry);
if (should_retry) {
// Create new promise to handle exponential backoff
const backoff = new Promise(function (resolve) {
setTimeout(function () {
resolve();
}, config.retryDelay || 1);
});
return backoff.then(() => {
return instance(config);
});
}
error.config.metadata.endTime = new Date();
error.duration =
error.config.metadata.endTime - error.config.metadata.startTime;
return Promise.reject(error);
} catch (err) {
console.log(`got error in try-catch`, err);
error.config.metadata.endTime = new Date();
error.duration =
error.config.metadata.endTime - error.config.metadata.startTime;
return Promise.reject(error);
}
}
);
Now export this instance from as a module and use it for network request.
instance({
method: "GET",
url,
timeout: 30000,
retry: 3,
retryDelay: 1000,
})
.then((response) => {
// console.log(`[response]`, response);
const { data, status, statusText } = response;
console.log(`status`, status);
console.log(`data`, data);
})
.catch((err) => {
const { status, statusText } = err.response || {};
console.log(`[error status]`, status, statusText);
// console.error(err);
});