Skip to content

Instantly share code, notes, and snippets.

@ezekielchentnik
Created August 12, 2016 16:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ezekielchentnik/670e27fdd400da46dd93be0608e53ef1 to your computer and use it in GitHub Desktop.
Save ezekielchentnik/670e27fdd400da46dd93be0608e53ef1 to your computer and use it in GitHub Desktop.
Session Storage interval caching with fetch and redux
const OPTIONS = {
credentials: 'include',
headers: {
'Accept': 'application/json', // eslint-disable-line
'Content-Type': 'application/json',
'X-Requested-With': 'XMLHttpRequest'
}
};
export function parseResponse(response) {
return response.json().then((json) => ({ json, response })); // provide parsed response and original response
}
export function checkStatus({ json, response }) {
if (!response.ok) { // status in the range 200-299 or not
return Promise.reject(new Error(response.statusText || 'Status not OK')); // reject & let catch decide how to handle/throw
}
return { json, response };
}
export function normalizeJSON({ json }) {
return json;
}
function hasStorage() {
const test = 'test';
try {
localStorage.setItem(test, test);
localStorage.removeItem(test);
return true;
} catch(e) {
return false;
}
}
function storeJSON(url, json) {
sessionStorage.setItem(url, JSON.stringify(json));
return json;
}
function getNearestTimestamp(interval){ // we round down to nearest interval
const coeff = 1000 * 60 * (interval || 5);
let date = new Date();
let rounded = new Date(Math.floor(date.getTime() / coeff) * coeff);
return rounded.getTime();
}
function defaultFetch(url, options){
return fetch(url, options || OPTIONS)
.then(parseResponse)
.then(checkStatus)
.then(normalizeJSON);
}
function makeFetch(url, options) {
if(hasStorage()){
const interval = 5; // use interval for cache key, expire every 5 mins
const stamp = getNearestTimestamp(interval);
const key = `${url}?_=${stamp}`;
const json = JSON.parse(sessionStorage.getItem(key));
if(json){
console.log(`[sessionStorage] ${key}`);
return Promise.resolve(json);
}
return defaultFetch(url, options)
.then((json) => storeJSON(key, json));
}
return defaultFetch(url, options);
}
function startAction(type) {
return { type };
}
function successAction(type, json) {
return { type, payload: json, meta: { receivedAt: Date.now() } };
}
function failureAction(type, error) {
return { type, payload: error, error: true, meta: { receivedAt: Date.now() } };
}
export const MY_DATA_REQUEST = 'MY_DATA_REQUEST';
export const MY_DATA_SUCCESS = 'MY_DATA_SUCCESS';
export const MY_DATA_FAILURE = 'MY_DATA_FAILURE';
export function fetchMyData() {
return (dispatch) => {
dispatch(startAction(MY_DATA_REQUEST));
return makeFetch(spendingURL)
.then((json) => dispatch(successAction(MY_DATA_SUCCESS, json)))
.catch((error) => dispatch(failureAction(MY_DATA_FAILURE, error)));
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment