在 ZSFT 实现热度值时,遇到了列出字体列表时需要同时调用热度值 fetch 函数导致重复的多次请求,即便 fetch 的函数已经设置了如果本地有数据则返回本地数据,但同时调用的时间点本地确实没有数据,也就导致了这一问题。(这样的问题或许很常见?)在网络上也无法找到相关的建议 ... 当然或许是我的搜索关键词有问题 ...
ZSFT 的方法是返回全站的热度值数据并在过期前使用本地缓存数据,因为那的确并不大,并且可以大幅度降低服务器压力,但如果为每个数据碎片化的单个请求,则不适用此方法。
以下请直接查看源代码,包括过期处理:
// 正在请求标识 let getThisFetching = false; // 返回的 Promise let getFetchPromise = null; async function get() { let obj = null; const localData = localStorage.getItem("localData"); const now = new Date(); const localDataTime = localStorage.getItem("localDataTime") ? new Date(localStorage.getItem("localDataTime")) : null; // 指定 1 天后过期,重新获取 const oneDay = (new Date(now.getTime() + (1 * 24 * 60 * 60 * 1000))).toISOString(); // 如果没有本地数据或者本地数据过期则执行,否则直接返回本地数据 if (!localData || (localDataTime && localDataTime < now)) { // 如果正在请求为 true 则不再请求而直接等待返回 if (!getThisFetching) { getThisFetching = true; getFetchPromise = fetch("XXX", { method: "GET", }).then(i => i.json()).then(data => { localStorage.removeItem("localDataTime"); localStorage.setItem("localDataTime", oneDay); localStorage.setItem("localData", JSON.stringify(data)); getThisFetching = false; getFetchPromise = null; return data; }).catch(error => { getThisFetching = false; getFetchPromise = null; throw error; }); }; obj = await getFetchPromise; } else { obj = JSON.parse(localData); }; return obj; };
实际上,这段代码和正常的可返回本地数据的 fetch 请求一样,只不过增加了两个变量,
首先,判断 !getThisFetching 也就是是否正在被请求,如果是,则不执行请求,包括请求前,会将 getThisFetching 设置为 true ,代表正在请求, fetch 被赋值给 getFetchPromise ,这样就可以让 obj 等待它