Service Worker架构:高效Token处理与网络请求同步方案咨询
在Service Worker中实现带自动更新的Auth Token管理机制
核心实现思路
不需要复杂的Proxy或Observables,通过维护一个当前有效的token获取Promise就能解决问题:所有网络请求都等待这个Promise完成以获取最新token;每次需要更新token时,重新发起token请求并替换这个Promise,新的请求会自动等待最新的Promise结果,天然实现请求排队等待逻辑。
完整代码实现
// Service Worker 全局变量 let currentTokenPromise; const TOKEN_REFRESH_INTERVAL = 15 * 60 * 1000; // 15分钟 // 1. 封装获取/刷新token的函数 async function getOrRefreshToken() { // 如果已有正在进行的token请求,直接返回这个Promise,避免重复请求 if (currentTokenPromise) { return currentTokenPromise; } try { // 发起token请求(替换成你的实际token接口) const response = await fetch('/api/auth/token', { method: 'POST', credentials: 'include' // 若需要携带cookie认证 }); const data = await response.json(); const token = data.access_token; // 返回token,同时保存当前Promise currentTokenPromise = Promise.resolve(token); return token; } catch (error) { // 请求失败时重置Promise,避免后续请求一直等待失败的Promise currentTokenPromise = null; throw error; } } // 2. 初始化首次token获取 currentTokenPromise = getOrRefreshToken(); // 3. 设置定时刷新token setInterval(async () => { // 重置当前Promise,触发新的token请求 currentTokenPromise = null; await getOrRefreshToken(); }, TOKEN_REFRESH_INTERVAL); // 4. 拦截网络请求并添加token self.addEventListener('fetch', (event) => { // 只拦截需要授权的接口(根据你的实际需求调整) if (event.request.url.startsWith(self.location.origin + '/api/')) { event.respondWith( (async () => { try { // 等待当前token获取完成 const token = await currentTokenPromise; // 克隆请求并添加Authorization头 const authRequest = new Request(event.request, { headers: new Headers({ ...event.request.headers, 'Authorization': `Bearer ${token}` }) }); // 发送带授权的请求 return fetch(authRequest); } catch (error) { // token获取失败时,可返回错误或重定向到登录(根据你的业务逻辑处理) return new Response('Authentication failed', { status: 401 }); } })() ); } });
关键逻辑说明
- 请求排队机制:当token正在获取(无论首次还是刷新),所有新发起的接口请求都会
await currentTokenPromise,自动等待token请求完成后再继续,不会出现请求因token未就绪而失败的情况。 - 避免重复请求:
getOrRefreshToken函数会检查是否已有正在进行的token请求,确保同一时间只有一个token请求在发送,减少不必要的服务器压力。 - 生命周期重置:每次定时刷新时,先将
currentTokenPromise置为null,触发新的token请求,后续的请求会自动等待这个新的Promise,实现token生命周期的重置。 - 错误处理:token请求失败时会重置Promise,避免后续请求一直绑定到失败的Promise上,同时在fetch拦截中可以根据业务需求处理认证失败的情况。
关于Proxy/Observables的补充
你提到的Proxy方案虽然能实现"可更新Promise",但对于Service Worker这种轻量环境来说,上述基于单一Promise的方案更简洁、易维护,不需要额外的抽象层。如果后续需要更复杂的状态监听(比如token过期前提前刷新、多状态通知),再考虑引入Observables会更合适,但当前需求用原生Promise完全足够。
内容的提问来源于stack exchange,提问作者UmbQbify
相关产品推荐
相关产品推荐

