Promise封装配置拉取器的核心是:首次网络请求成功后写入localStorage并返回;后续先读缓存(强缓存,不校验服务端),同时后台更新,若新数据有效则覆盖缓存并通知监听者;缓存结构含timestamp和version,读取时校验本地过期窗口。

用Promise封装带本地强缓存和失效更新的配置拉取器
核心思路是:首次请求走网络,成功后写入 localStorage 并返回;后续请求先读缓存(强缓存,不校验服务端),同时在后台发起新请求,若响应有更新则覆盖缓存并通知监听者(可选)。关键在于“读缓存不阻塞、更新缓存不打断当前流程”。
缓存策略与过期控制
强缓存意味着不主动发请求验证有效性,但需要避免永久 stale。推荐在缓存数据中嵌入时间戳或版本号,并设定本地过期窗口(如 10 分钟)。不是靠服务端 Cache-Control,而是由 JS 自行判断:
- 缓存对象结构建议为:
{ data: {...}, timestamp: 1717023456789, version: "v2.1" } - 读取时检查
Date.now() - cached.timestamp ,超时则视为“需后台刷新”,但仍返回旧数据 - 不强制要求每次调用都等网络,除非显式传参
{ force: true }
基础 Promise 封装实现
以下是一个简洁可靠的封装(无第三方依赖):
function createConfigFetcher(url, options = {}) {
const { cacheKey = 'config_data', ttlMs = 10 * 60 * 1000 } = options;
<p>async function fetchWithCache() {
// 1. 尝试读本地缓存
const cached = localStorage.getItem(cacheKey);
if (cached) {
try {
const parsed = JSON.parse(cached);
const now = Date.now();
if (now - parsed.timestamp </p><pre class="brush:php;toolbar:false;">// 2. 缓存无效或不存在:走网络 + 写缓存
const res = await fetch(url);
if (!res.ok) throw new Error(`HTTP ${res.status}: ${res.statusText}`);
const data = await res.json();
// 写入带时间戳的缓存
const cacheValue = { data, timestamp: Date.now(), version: data.version || 'unknown' };
localStorage.setItem(cacheKey, JSON.stringify(cacheValue));
return data;}
// 后台静默刷新(失败不抛错,不影响主流程) async function refreshInBackground() { try { const res = await fetch(url); if (!res.ok) return; const data = await res.json(); const cached = localStorage.getItem(cacheKey); const old = cached ? JSON.parse(cached) : null; // 可选:只在版本变化时更新缓存 if (!old || old.version !== data.version) { localStorage.setItem(cacheKey, JSON.stringify({ data, timestamp: Date.now(), version: data.version || 'unknown' })); } } catch (e) { // 静默失败,不干扰用户 } }
// 暴露 fetch 方法和手动刷新方法 fetchWithCache.refresh = refreshInBackground; return fetchWithCache; }
// 使用示例 const fetchConfig = createConfigFetcher('/api/config', { cacheKey: 'app_config_v2', ttlMs: 5 60 1000 // 5 分钟强缓存 });
// 调用即用,自动缓存/后台更新 fetchConfig().then(config => { console.log('拿到配置:', config); });
增强可用性的小技巧
让这个拉取器更健壮实用:
-
错误降级:网络失败且无有效缓存时,可 fallback 到内置默认配置(如
const DEFAULT_CONFIG = { theme: 'light', lang: 'zh' }) -
防抖刷新:如果页面多个地方同时调用
fetchConfig(),可加简单节流(例如用Promise缓存未完成的请求)避免重复请求 -
监听变更:配合
CustomEvent或简单回调,在后台更新成功后广播事件,便于 UI 响应式刷新 -
清除缓存:暴露
clearCache()方法,方便开发调试或强制重载
不复杂但容易忽略:强缓存 ≠ 不更新,而是“先快后准”。Promise 封装的关键是把异步逻辑分层 —— 主流程保证快,副作用保证准。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











