arthurfiorette / axios-cache-interceptor

📬 Small and efficient cache interceptor for axios. Etag, Cache-Control, TTL, HTTP headers and more!

Home Page:https://axios-cache-interceptor.js.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Handle infinite `loading` states when a restart occurs in the middle of a request.

arthurfiorette opened this issue · comments

When using any kind of persisted storage, the app may restart while a request is in loading waiting for it to finish. In this case, the request will arrive here:

/* istanbul ignore if 'really hard to test' */
if (!deferred) {
await axios.storage.remove(id, config);
// Hydrates any UI temporarily, if cache is available
if (cache.data) {
await config.cache.hydrate?.(cache);
}
return config;
}

Which is when we have a loading state but no deferred is registered (as it is a in memory promise hash map). Previously we just deleted the cache and continued with a empty response to be handled by the response interceptor.

If the response of this request comes successful, it would ignore caching and return here:

if (
// If the request interceptor had a problem or it wasn't cached
cache.state !== 'loading'
) {
if (__ACI_DEV__) {
axios.debug?.({
id,
msg: "Response not cached and storage isn't loading",
data: { cache, response }

Or, if this response failed, it would re-throw the error thinking the interceptor broke:

if (
// This will only not be loading if the interceptor broke
cache.state !== 'loading' ||
cache.previous !== 'stale'
) {
await rejectResponse(id, config);
if (__ACI_DEV__) {
axios.debug?.({
id,
msg: 'Caught an error in the request interceptor',

The responses interceptors are right to expect a loading state, otherwise non loading requests should've been resolved from the request interceptor already.

To solve this problem, the check below must be done in the ignoreAndRequest code block to fix the cache to loading before returning the response.

if (cache.state === 'loading') {
const deferred = axios.waiting[id];