使用函数式编程实现接口缓存
假设我们需要请求一个接口
1 2 3 4 5 6 7 8 9 10 11 12 13
| const get = (url, params) => Promise.resolve(params);
const getData = (params) => get("/api", params);
const appendDiv = (text) => { const div = document.createElement("div"); div.innerText = text; document.body.appendChild(div); };
getData({ q: 123 }).then((data) => { appendDiv(JSON.stringify(data)); });
|
使用缓存优化性能
现在为了性能优化,我们需要对性能优化需要做缓存处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
const cacheMap = {};
const getKey = (url, params) => JSON.stringify({ __url: url, ...params, });
const params = { q: 123 }; const key = getKey("/api", params);
const handleData = (data) => appendDiv(JSON.stringify(data));
if (cacheMap[key]) { handleData(cacheMap[key]); } else { getData(params).then((data) => { cacheMap[key] = data; handleData(data); }); }
|
利用代理模式分离缓存和业务逻辑
我们可以利用代理模式的思路,将缓存和请求分离开来
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| const getDataProxy = async (params) => { const key = getKey("/api", params); if (cacheMap[key]) { return cacheMap[key]; } return getData(params); };
const handleDataProxy = (params, data) => { const key = getKey("/api", params); cacheMap[key] = data; handleData(data); };
getDataProxy(params).then((data) => handleDataProxy(params, data));
|
使用 currying 和高阶函数复用代码
虽然我们现在把当前请求的缓存和请求分离开来,但是只限定当前请求,并不能通用化
我们使用高阶函数来实现代码复用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| import { compose, tap, curry } from "lodash/fp";
const ifElse = (flag, firstFun, secondFun) => { return flag ? firstFun : secondFun; };
const getCache = (key) => cacheMap[key];
const setCache = curry((key, data) => (cacheMap[key] = data));
const proxyRequest = curry((url, request, params) => { const key = getKey(url, params); return ifElse(getCache(key), () => getCache(key), request)(params); });
const proxyHandleData = curry((url, handleData, params, data) => { const key = getKey(url, params); setCache(key, data); handleData(data); });
const getDataProxy = proxyRequest("/api", getData); const handleDataProxy = proxyHandleData("/api", handleData);
getDataProxy(params).then(handleDataProxy(params));
|