Open JeromeD3 opened 1 year ago
数据共享肯定得找个东西把数据存放才能共享啦
创建一个map用来存同一个
key
的promise
请求函数 --> 这里是缓存请求函数哦
const cachePromise = new Map();
const getCachePromise = cacheKey => {
return cachePromise.get(cacheKey);
};
const setCachePromise = (cacheKey, promise) => {
cachePromise.set(cacheKey, promise);
promise.then(res => {
cachePromise.delete(cacheKey);
return res;
}).catch(() => {
cachePromise.delete(cacheKey);
});
};
export { getCachePromise, setCachePromise };
接着用发布订阅模式定义一个函数,规定了什么时候缓存这些请求,什么时候执行这些请求
const listeners = {};
const trigger = (key, data) => {
if (listeners[key]) {
listeners[key].forEach(item => item(data));
}
};
const subscribe = (key, listener) => {
if (!listeners[key]) {
listeners[key] = [];
}
listeners[key].push(listener);
return function unsubscribe() {
const index = listeners[key].indexOf(listener);
listeners[key].splice(index, 1);
};
};
export { trigger, subscribe };
有了上面两大函数,我们可以修改useCachePlugin,新增代码如下:
import { useRef } from 'react';
import * as cache from '../utils/cache';
import useCreation from '../../../useCreation';
+import * as cachePromise from '../utils/cachePromise';
+import * as cacheSubscribe from '../utils/cacheSubscribe';
const useCachePlugin = (fetchInstance, {
cacheKey,
staleTime = 0,
cacheTime = 5 * 60 * 1000,
setCache: customSetCache,
getCache: customGetCache
}) => {
+ const unSubscribeRef = useRef();
+ const currentPromiseRef = useRef();
const _setCache = (key, cachedData) => {
if (customSetCache) {
customSetCache(cachedData);
} else {
cache.setCache(key, cacheTime, cachedData);
}
+ cacheSubscribe.trigger(key, cachedData.data);
};
const _getCache = (key, params) => {
if (customGetCache) {
return customGetCache(params);
}
return cache.getCache(key);
};
useCreation(() => {
if (!cacheKey) {
return;
}
const cacheData = _getCache(cacheKey);
if (cacheData && Object.hasOwnProperty.call(cacheData, 'data')) {
fetchInstance.state.data = cacheData.data;
fetchInstance.state.params = cacheData.params;
if (staleTime === -1 || new Date().getTime() - cacheData.time <= staleTime) {
fetchInstance.state.loading = false;
}
}
})
if (!cacheKey) {
return {};
}
return {
onBefore: params => {
const cacheData = _getCache(cacheKey, params);
if (!cacheData || !Object.hasOwnProperty.call(cacheData, 'data')) {
return {};
}
if (staleTime === -1 || new Date().getTime() - cacheData.time <= staleTime) {
return {
loading: false,
data: cacheData?.data,
returnNow: true
};
} else {
return {
data: cacheData?.data
};
}
},
+ onRequest: (service, args) => {
+ let servicePromise = cachePromise.getCachePromise(cacheKey);
+ if (servicePromise && servicePromise !== currentPromiseRef.current) {
+ return {
+ servicePromise
+ };
+ }
+ servicePromise = service(...args);
+ currentPromiseRef.current = servicePromise;
+ cachePromise.setCachePromise(cacheKey, servicePromise);
+ return {
+ servicePromise
+ };
+ },
onSuccess: (data, params) => {
if (cacheKey) {
_setCache(cacheKey, {
data,
params,
time: new Date().getTime()
});
+ unSubscribeRef.current = cacheSubscribe.subscribe(cacheKey, d => {
+ fetchInstance.setState({
+ data: d
+ });
+ });
+ }
}
};
};
export default useCachePlugin;
前提:map存的是结果,订阅函数存的是请求函数。
ref
用来表示当前的请求,其实也可以理解为上一次请求,因为不刷新的情况下,他保存的是上一次请求函数。promise
,如果有,且与上一次的请求不一样,(说明其他的组件需要更新了,直接返回缓存的)就直接返回给当前实例,实例拿到后直接请求。