-
-
Save javisperez/4bb09e0437994a659bbcd06f90eeebbf to your computer and use it in GitHub Desktop.
// Usually I use this in my app's config file, in case I need to disable all cache from the app | |
// Cache is from `js-cache`, something like `import Cache from 'js-cache';` | |
const cacheable = true, | |
cache = new Cache(); | |
// On request, return the cached version, if any | |
axios.interceptors.request.use(request => { | |
// Only cache GET requests | |
if (request.method === 'get' && cacheable) { | |
let url = request.url; | |
// Append the params, I use jquery param but you can change to whatever you use | |
if (request.params) | |
url += '?' + $.param(request.params); | |
const _cached = cache.get(url); | |
if (_cached) { | |
_cached.__fromCache = true; | |
console.log(`"${url}" served from cache:`, _cached); | |
request.data = _cached; | |
// Set the request adapter to send the cached response and prevent the request from actually running | |
request.adapter = () => { | |
return Promise.resolve({ | |
data: _cached, | |
status: request.status, | |
statusText: request.statusText, | |
headers: request.headers, | |
config: request, | |
request: request | |
}); | |
}; | |
} | |
} | |
return request; | |
}, error => Promise.reject(error)); | |
// On response, set or delete the cache | |
axios.interceptors.response.use(response => { | |
// if you dont want to cache a specific url, send a param `__cache = false` | |
const isCacheable = !response.config.params || (response.config.params && response.config.params.__cache !== false); | |
if (cacheable && isCacheable) { | |
let url = response.config.url; | |
if (response.config.params) | |
url += '?' + $.param(response.config.params); | |
if (response.config.method === 'get') { | |
// On get request, store the response in the cache | |
cache.set(url, response.data); | |
} else { | |
// For post, put or delete, just delete the cached version of the url | |
// e.g. posting to `/users` would delete the `/users` cache, so when you ask for users again you get the real version | |
cache.del(response.config.url); | |
// also, when making a post,put or delete request to `/users/1`, would try to delete the `/users` for the same reason | |
const uri = url.replace(config.http.api.base_url, ''), | |
parentUri = /(.*)\/([a-z0-9\-]+)\/?$/ig.exec(uri); | |
if (parentUri) | |
cache.del(`${config.http.api.base_url}${parentUri[1]}`); | |
// Delete similar url that just have query string diferences | |
// Specially useful for things like Laravel's `with` param | |
// e.g. `/users?with=permissions` will get cached but the post to `/users` wont remove it from the cache | |
// so I look all the cached url's and try to match it without the querystrings | |
const urls = Object.keys(cache.debug()); | |
for (const _url of urls) { | |
if (_url.match(/^[^?]+/)[0] === response.config.url) | |
cache.del(_url); | |
} | |
} | |
} | |
return response; | |
}, error => Promise.reject(error)); |
Nice work man. Have you had any issues using Cache api? MDN still shows it as a experimental feature...
Great job! I was looking for how to terminate original request from network! Thanks!
Awesome man, this saved my day trying terminate axios request when I already have the cached version
Good example! A while ago i started with something like that and ended up with my own small library.
If anyone wants to try it out: axios-cache-interceptor
Here's an example:
import axios from 'axios';
import { setupCache } from 'axios-cache-interceptor';
setupCache(axios);
const req1 = axios.get('https://api.example.com/');
const req2 = axios.get('https://api.example.com/');
const [res1, res2] = await Promise.all([req1, req2]);
res1.cached // false
res2.cached // true
@arthurfiorette
I have tried it, it's so cool!!! But I have a question about buildMemoryCache's useful, that after I reload the page, and request the prev API URL cached before. My expectation is that request will get from the memory cache, but it actually makes a new request again (TTL still valid). Is my knowledge wrong with the docs? (https://axios-cache-interceptor.js.org/#/pages/storages)
Hey, the memory storage does what it is capable of, when you reload a page any variable is erased. What you want to do is use web storages as described in the docs too.
gorgeous