I'm using axios as my data fetching library. The use case is that - the auth token expires every 30 minutes so once it expires, I've created an interceptor to catch the 401 and refresh the token. However, the issue is that every API call invokes the authentication API. Ideally, it should only happen once.
Here's the code that sets the default request headers
let refreshTokenPromise;
wrappedAxiosInstance.interceptors.request.use(
async (config) => {
const token = AuthService.getAuthServiceInstance().getAuthToken();
// eslint-disable-next-line no-param-reassign
config.headers.Authorization = `Bearer ${token}`;
return config;
},
error => Promise.reject(error)
);
wrappedAxiosInstance.interceptors.response.use(
response => response,
async (error) => {
const originalRequest = error.config;
if (error.response.status === 401 && error.response.data.error === TOKEN_EXPIRED && !originalRequest._retry) {
originalRequest._retry = true;
if (!refreshTokenPromise) {
// eslint-disable-next-line no-use-before-define
refreshTokenPromise = api.auth.login().then((data) => {
refreshTokenPromise = null;
return data;
});
}
// Can't get a reference to the token here. It never gets invoked
const { token } = await refreshTokenPromise();
console.log('result', token);
}
return Promise.reject(error);
}
);
Here are sample API calls that consume this -
api.posts = {
async list() {
const response = await wrappedAxiosInstance.get(
`${HOST}/policies`,
// { headers: AuthService.getAuthServiceInstance().withAuthHeaders() }
);
if (response.status !== 200) {
throw new ApiError(response.data);
}
return response.data;
}
};
api.comments = {
async list() {
const response = await wrappedAxiosInstance.get(
`${HOST}/controls`,
// { headers: AuthService.getAuthServiceInstance().withAuthHeaders() }
);
if (response.status !== 200) {
throw new ApiError(response.data);
}
return response.data;
}
};
Essentially, the comments and posts both call the login. What I'm trying to achieve is that the call should only be made once.