// From https://www.sitepoint.com/cache-fetched-ajax-requests/ // All credits to: Peter Bengtsson // Added Content-type to headers so it can go to traditional validation like fetch does // Add some debugging messages: activate with { verbose: true } // Add a request to be able to add headers instead of just calling URL const CachedFetch = (url, options) => { let expiry = options.seconds || 5 * 60 // 5 min default let logger = (options.verbose) ? console.log : function(){}; // logger( url, expiry, options); // Use the URL as the cache key to sessionStorage let cacheKey = url let cached = localStorage.getItem(cacheKey) let whenCached = localStorage.getItem(cacheKey + ':ts') if (cached !== null && whenCached !== null) { // it was in sessionStorage! Yay! // Even though 'whenCached' is a string, this operation // works because the minus sign converts the // string to an integer and it will work. let age = (Date.now() - whenCached) / 1000 if (age < expiry) { let response = new Response(new Blob([cached])) response.headers.set("Content-Type","application/json; charset=utf-8") logger("[cachedFetch] Returning cached result"); return Promise.resolve(response) } else { // We need to clean up this old key localStorage.removeItem(cacheKey) localStorage.removeItem(cacheKey + ':ts') } } let request = new Request(url, options.headers) logger("[cachedFetch] loading data", url); return fetch( request ).then(response => { logger('[cachedFetch] Response: ', response.headers.get('Content-Type')); // let's only store in cache if the content-type is // JSON or something non-binary if (response.status === 200) { let ct = response.headers.get('Content-Type') if (ct && (ct.match(/application\/json/i) || ct.match(/text\//i))) { // There is a .json() instead of .text() but // we're going to store it in sessionStorage as // string anyway. // If we don't clone the response, it will be // consumed by the time it's returned. This // way we're being un-intrusive. response.clone().text().then(content => { logger('[cachedFetch] Caching '); localStorage.setItem(cacheKey, content) localStorage.setItem(cacheKey+':ts', Date.now()) }) } } logger('[cachedFetch] Returning server response'); return response }) } export default CachedFetch;