FE-Interview
FE-Interview copied to clipboard
请实现一个 cacheRequest 方法,保证发出多次同一个 ajax 请求时都能拿到数据,而实际上只发出一次请求
扫描下方二维码,获取答案以及详细解析,同时可解锁800+道前端面试题。
const cacheRequest = (() => {
const cacheMap: Map<string, CacheInfo
return <T>(p: () => Promise<T>, options: Params<T>) => { const cache = cacheMap.get(options.url) if (cache?.data) { if (cache.expireTime && Date.now() > cache.expireTime) { cacheMap.delete(options.url) } else { options.onSuccess(cache.data) return } }
const isCache = cacheMap.has(options.url)
if (!isCache) {
if (cacheMap.size >= 10) {
const firstKey = cacheMap.keys().next().value
cacheMap.delete(firstKey)
}
cacheMap.set(options.url, {
data: null,
onSucCallbacks: [],
expireTime: options.expireTime ? Date.now() + options.expireTime : 60 * 1000,
})
p().then(data => {
const cache = cacheMap.get(options.url)
cache.data = data
cache.onSucCallbacks.forEach(cb => {
cb(data)
})
})
}
cacheMap.get(options.url)?.onSucCallbacks.push(options.onSuccess)
} })()
interface CacheInfo<T> { data: T | null onSucCallbacks: ((data: T) => void)[] expireTime: number }
interface Params<T> { url: string onSuccess: (data: T) => void expireTime?: number }
cacheRequest 实现
const cacheRequest = () => {
const cache = new Map();
/**
* 生成正确的 cache key
*
* @author Harper.Gao
* @param {*} url
* @param {*} options
* @return {*}
*/
const generateCacheKey = (url, options) => {
return `${url}${JSON.stringify(options)}`;
};
return async (url, options = {}) => {
return new Promise(resolve => {
const currentRequestKey = generateCacheKey(url, options);
console.log(`Start handle url: ${url}, currentRequestKey: ${currentRequestKey}`);
if (cache.has(currentRequestKey)) {
console.log(`Current request hit cache! return result`);
return resolve(cache.get(currentRequestKey));
}
const promise = fetch(url, options);
cache.set(currentRequestKey, promise);
promise.then(result => {
cache.set(currentRequestKey, result);
resolve(result);
});
});
};
};
调用
const CacheRequest = () => {
const request = cacheRequest();
const onClickHandler = async () => {
const result = await request("http://localhost:9090/api/getimmortal");
console.log("result", result);
};
return (
<div>
<button onClick={onClickHandler}>Do cache request handler</button>
</div>
);
};