Bug: staleIfError + overrides don't seem to work on blocked requests
bperel opened this issue · comments
What happened?
I would like to mimic an offline mode behavior with axios-cache-interceptor.
If I understood the documentation properly, this can be done with a combination of overrides
(I always want to retrieve the most recent data from the API) + staleIfError: true
(if the user is offline, I want to failover to the cached version).
This is the sandbox that I tried it on:
https://codesandbox.io/s/stateiferror-n9kdr8
- First, I click on the "Get" button. As expected, the data gets retrieved then cached.
- Then, I block the request using Firefox developer tools:
![Screenshot 2023-10-17 at 21 24 25](https://private-user-images.githubusercontent.com/1484692/275976326-cf363c18-beef-41b2-8445-1331024c2e5a.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MTI5NDUwNjIsIm5iZiI6MTcxMjk0NDc2MiwicGF0aCI6Ii8xNDg0NjkyLzI3NTk3NjMyNi1jZjM2M2MxOC1iZWVmLTQxYjItODQ0NS0xMzMxMDI0YzJlNWEucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI0MDQxMiUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNDA0MTJUMTc1OTIyWiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9YjgxMzViODZkNTc2Y2MzNTRjMGM4ZDNiMTk4MjdkODA3ZDdhZDczMDQzOGVhYjVkMDM0MzliNTE0NjE1ODExMiZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QmYWN0b3JfaWQ9MCZrZXlfaWQ9MCZyZXBvX2lkPTAifQ.ffeEYviRa-bhf9iE5ob8A7JWGk7JU_b00KwQCjVK9LY)
I would expect to see the message "custom predicate" in the console, but I don't, which seems to indicate that staleIfError
doesn't work as I'm thinking it should. Am I doing something wrong?
axios-cache-interceptor version
v1.3.1
Node / Browser Version
Firefox 118
Axios Version
v1.5.1
What storage is being used
Web Storage
Relevant debugging log output
[{
"id": "fetch-products",
"msg": "Sending request, waiting for response",
"data": {
"overrideCache": false,
"state": "empty"
}
}, {
"id": "fetch-products",
"msg": "Useful response configuration found",
"data": {
"cacheConfig": {
"update": {},
"ttl": 300000,
"methods": [
"get",
"head"
],
"cachePredicate": {},
"etag": true,
"modifiedSince": false,
"interpretHeader": true,
"cacheTakeover": true,
"override": false
},
"cacheResponse": {
"data": {
"products": [...],
"total": 100,
"skip": 0,
"limit": 30
},
"status": 200,
"statusText": "",
"headers": {
"content-type": "application/json; charset=utf-8",
"x-axios-cache-stale-if-error": "300000"
}
}
}
}, {
"id": "fetch-products",
"msg": "Found waiting deferred(s) and resolved them"
},{
"id": "fetch-products",
"msg": "Response cached",
"data": {
"cache": {
"state": "cached",
"ttl": 300000,
"createdAt": 1697618799248,
"data": {
"data": {
"products": [...],
"total": 100,
"skip": 0,
"limit": 30
},
"status": 200,
"statusText": "",
"headers": {
"content-type": "application/json; charset=utf-8",
"x-axios-cache-stale-if-error": "300000"
}
}
},
"response": {
"data": {
"products": [...],
"total": 100,
"skip": 0,
"limit": 30
},
"status": 200,
"statusText": "",
"headers": {
"content-type": "application/json; charset=utf-8",
"x-axios-cache-stale-if-error": "300000"
},
"config": {
"transitional": {
"silentJSONParsing": true,
"forcedJSONParsing": true,
"clarifyTimeoutError": false
},
"adapter": [
"xhr",
"http"
],
"transformRequest": [
null
],
"transformResponse": [
null
],
"timeout": 0,
"xsrfCookieName": "XSRF-TOKEN",
"xsrfHeaderName": "X-XSRF-TOKEN",
"maxContentLength": -1,
"maxBodyLength": -1,
"env": {},
"headers": {
"Accept": "application/json, text/plain, */*",
"Content-Type": null,
"cache-control": "no-cache",
"pragma": "no-cache",
"expires": "0"
},
"baseURL": "https://dummyjson.com",
"cache": {
"update": {},
"ttl": 300000,
"methods": [
"get",
"head"
],
"cachePredicate": {},
"etag": true,
"modifiedSince": false,
"interpretHeader": true,
"cacheTakeover": true,
"override": false
},
"id": "fetch-products",
"method": "get",
"url": "/products"
},
"request": {},
"id": "fetch-products",
"cached": false
}
}
}, /* This is where I blocked the URL*/
{
"id": "fetch-products",
"msg": "Returning cached response"
} , {
"id": "fetch-products",
"msg": "Returned cached response"
}]
Please attach debug logs
Please attach debug logs
Done
Your request is being sent to the network, then cached. Even if you block the request URL, subsequent request won't even reach your network tab in devtools because they are being cached at the javascript step.
Isn't this the correct behaviour? What should've been happening?
Since I assigned a function to the staleIfError
option, I would expect that each time I make an axios request, this function is called since it's supposed to determine if the current request should return the existing cached response.
Moreover, since I specified override: true
, I would expect the request to be made anyway since, if I understood the documentation properly, This option bypasses the current cache and always make a new http request
.
@arthurfiorette Are my assumptions correct?
Hey @bperel. I simply tried out your reproducible example. After the first response is returned, it is put into the cache for subsequent requests. You blocking/unblocking a request won't have any effect until the cache expires.
As you can see in the debug logs:
{
"id": "fetch-products",
"msg": "Returning cached response"
}
{
"id": "fetch-products",
"msg": "Returned cached response"
}
staleIfError
, as the majority of other options, are only called if a request/cache revalidation is needed. While the request has fresh cache, it will not call staleIfError
.
Actually, this exactly problem was a bug when applying override
globally.
// does not work in v1.3.1
setupCache(axios, { override: true });
axios.get('url')
// works in v1.3.1
setupCache(axios);
axios.get('url', { cache: { override: true } })
Fixed in v1.3.2