Skip to content

Instantly share code, notes, and snippets.

@miteshmap
Last active June 10, 2020 15:32
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 miteshmap/25f03b7943da9824625a072fd4cd173c to your computer and use it in GitHub Desktop.
Save miteshmap/25f03b7943da9824625a072fd4cd173c to your computer and use it in GitHub Desktop.
React Fetcher with cache for axios request, based on a talk of Dan Abramov: https://youtu.be/nLF0n9SACd4?t=877
import CacheSearch from "./CacheSearch";
let tempCacheObjects = {};
/**
* Helper function to initiate only single object
* for any given promise function name.
*/
export const createCacheObject = func => {
if (typeof tempCacheObjects[func.name] === "undefined") {
tempCacheObjects[func.name] = new CacheSearch();
}
return tempCacheObjects[func.name];
};
/**
* Cache class for search.
*
* Avoid unnecessary api request by caching the results.
*/
class CacheSearch {
constructor() {
this.query = '';
this.queryCount = 0;
this.cache = {};
this.cacheHits = 0;
this.cacheHitsHistory = [];
}
getResults(query) {
this.query = JSON.stringify(query);
if (this.cache[this.query]) {
this.cacheHits = this.cacheHits + 1;
this.queryCount = this.queryCount + 1;
this.cacheHitsHistory.concat(this.query);
return this.cache[this.query];
}
return null;
}
cacheResult(results) {
this.cache[this.query] = results;
this.queryCount = this.queryCount + 1;
return results;
}
}
export default CacheSearch;
import { createCacheObject } from "./cache-objects";
/**
* Helper function to handle api request for GET method for now.
*
* Created helper method to avoid error handling everytime we make
* api requests. This general function will always be used to make
* api request, and it handles caching, returns error correctly so
* on usage does not have to do comoplicated condition check and
* returns data in promise.
*
* @param {*} promiseFunc
* Promise function name.
*/
export const createFetcher = promiseFunc => {
return {
read: arg => {
// Initiate cache and cache responses of stores to avoid
// Duplicate api calls.
let cachedObj = createCacheObject(promiseFunc);
let cachedResults = cachedObj.getResults(arg);
if (!cachedResults) {
try {
return promiseFunc(arg).then(
response => {
if (!response) {
return { error: "error!" };
}
if (typeof response.data !== "object") {
return { error: "error!" };
}
if (!response.data.error && response.data.error) {
console.error(cart_result.error_message);
return { error: "error!" };
}
cachedObj.cacheResult(response.data);
return response.data;
},
reject => {
return { error: reject };
}
);
} catch (error) {
return new Promise(resolve => resolve({ error: error }));
}
}
// read: should always return promise, so that we don't have to
// check at api call point if it's a promise or not.
return new Promise(resolve => resolve(cachedResults));
}
};
};
@miteshmap
Copy link
Author

miteshmap commented Mar 1, 2020

USAGE:

export const fetchItems = arg => {
  const GET_ITEMS = url(`fetch/item/${arg.id}`);
  return Axios.get(GET_ITEMS);
};

const newFetcher = createFetcher(fetchItems);
// this will trigger api request.
let list = newFetcher.read({id: 1});

list.then(
  response => {
    if (typeof response.error !== 'undefined') {
     // Track errors..
     console.error(response.error);
    }
    else {
       this.setState({item: response});
    }
  }
);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment