如何在无Service Worker更新时触发操作并隐藏启动屏
解决Service Worker无更新检测与启动屏隐藏问题
核心思路
要实现「无更新时隐藏启动屏、有更新时完成安装后再隐藏」,需要结合Service Worker的注册状态、更新事件、激活状态判断逻辑,同时避免更新后页面刷新重复触发启动屏的循环问题。
具体实现代码
// 假设启动屏DOM选择器为#splash-screen const splashScreen = document.getElementById('splash-screen'); if ("serviceWorker" in navigator) { window.addEventListener("load", async () => { try { const reg = await navigator.serviceWorker.register("./service-worker.js"); console.log("Service worker registered:", reg); // 1. 主动检查是否有可用更新 const hasUpdate = await checkForUpdates(reg); if (!hasUpdate) { // 当前已是最新版本,直接隐藏启动屏 hideSplashScreen(); return; } // 2. 有更新时,监听新Service Worker的安装状态 reg.addEventListener('updatefound', () => { const newWorker = reg.installing; newWorker.addEventListener('statechange', () => { if (newWorker.state === 'installed') { if (navigator.serviceWorker.controller) { // 页面仍被旧版SW控制,刷新页面让新版SW激活 window.location.reload(); } else { // 首次安装完成,直接隐藏启动屏 hideSplashScreen(); } } }); }); // 3. 监听SW控制变更事件(新版SW激活后触发) navigator.serviceWorker.addEventListener('controllerchange', () => { // 新版SW激活后,再次确认无更新并隐藏启动屏 checkForUpdates(reg).then(updateExists => { if (!updateExists) hideSplashScreen(); }); }); } catch (err) { console.error("Service worker registration failed:", err); // 注册失败时直接隐藏启动屏,避免阻塞应用 hideSplashScreen(); } }); } else { // 浏览器不支持Service Worker,直接隐藏启动屏 hideSplashScreen(); } // 检查是否有可用更新的工具函数 async function checkForUpdates(reg) { try { // 主动触发更新检查,返回true表示有更新正在下载,false表示当前已是最新 return await reg.update(); } catch (err) { console.error("Failed to check for updates:", err); // 检查失败默认视为无更新,避免卡住启动屏 return false; } } // 隐藏启动屏的工具函数 function hideSplashScreen() { if (splashScreen) { splashScreen.style.display = 'none'; // 可添加过渡动画效果:splashScreen.classList.add('fade-out'); } }
关键逻辑说明
- 主动更新检查:通过
reg.update()主动触发更新检测,返回false时直接判定为当前已是最新版本,立即隐藏启动屏。 - 更新流程处理:当检测到更新后,等待新版SW安装完成,若页面仍被旧版SW控制则刷新页面,让新版SW激活生效。
- 控制变更监听:新版SW激活后触发
controllerchange事件,再次确认无更新后隐藏启动屏,解决更新后刷新页面重复显示启动屏的问题。 - 异常兜底:注册失败或更新检查失败时,默认隐藏启动屏,避免阻塞应用正常使用。
内容的提问来源于stack exchange,提问作者maxischl
相关产品推荐
相关产品推荐

