// 1. Define the Cache Structure
export class MapCache {
map = new Map();
static getKey(parmas) {
return JSON.stringify(parmas);
}
get(key) {
return this.map.get(key) && this.map.get(key).value;
}
set(key, value) {
return this.map.set(key, { value, timestamp: Date.now() });
}
// Check if cache is hit based on maxTime
hit(key, maxTime) {
const { timestamp = 0 } = this.map.get(key) || {};
return (Date.now() - timestamp < maxTime);
}
}
// 2. Create the Decorator to extend request methods
export function apiHelper(fn) {
const apiCache = new MapCache();
return function (...args) {
let cache = false;
// Check if caching is enabled (passed as the last argument)
if (args.length === 2) {
cache = args.splice(-1)[0];
}
if (!cache) {
return fn.apply(this, args);
}
// Handle cache configuration
const { maxTime } = typeof cache === 'boolean' ? { maxTime: 1000 } : cache;
const { url, params, data, method } = args[0];
const key = MapCache.getKey({ url, params, data, method });
if (apiCache.hit(key, maxTime)) {
return apiCache.get(key);
}
const response = fn.apply(this, args);
// Store the response (supports merging concurrent requests into one Promise)
apiCache.set(key, response);
return response;
};
}
// 3. Usage Example with Axios
import Axios from 'axios';
const request = apiHelper(Axios.request);
// Request with caching enabled (default 1000ms)
request({ url: 'http://api.twitter.com', params: { a: 1 } }, true);