处理Service Worker更新时,是否真的需要所有这些多重检查?
问题背景
我跟着Jake Archibald在Udacity的《离线Web应用》教程学习Service Worker,对教程里更新练习的解决方案框架有疑问。这个方案包含三个检查,对应三种更新状态,但我测试后只触发了第三个(reg.waiting)。
我的测试步骤:
- 在
localhost:8080首次加载页面,完成Service Worker的注册、安装和激活 - 修改Service Worker(比如在缓存文件数组中添加
/tmp.txt) - 刷新页面
首次刷新没触发任何检查,第二次刷新触发了reg.waiting检查。我懂Service Worker生命周期,但不清楚另外两个检查(updatefound事件监听、installingSw检查)的触发场景,想确认这三个检查是否都有必要?
教程提供的代码:
(async() => { if ("serviceWorker" in navigator) { try { const reg = await navigator.serviceWorker.register("/sw.js"); if (!reg || !navigator.serviceWorker.controller) { return; } // Possible states of new updates: // - 1. There are no updates yet, a new update may arrive // - 2. An update is in progress // - 3. A waiting update exists (already installed) // 1. addEventListener("updatefound", () => { console.log("updatefound"); const sw = reg.installing; trackInstallation(sw); }); // 2 const installingSw = reg.installing; if (installingSw) { console.log("installingSw"); trackInstallation(installingSw); return; } // 3 if (reg.waiting) { console.log("reg.waiting"); const sw = reg.waiting; notifyUpdate(); return; } console.log("nothing"); } catch (error) { console.error("Service worker registration failed.", error); } } })(); function trackInstallation(worker) { worker.addEventListener("statechange", () => { if (worker.state === "installed") { notifyUpdate(); } }); } function notifyUpdate() { alert("There's a new update!"); }
三个检查的触发场景解析
1. updatefound 事件监听(“暂无更新但可能到来”)
这个事件在浏览器检测到新的Service Worker文件(与当前激活SW的哈希值不一致),开始下载并进入安装阶段时触发。
你的测试流程里,第一次修改SW后刷新页面,浏览器会在后台异步执行更新检查、下载新SW并启动安装——但页面注册SW的代码执行时,updatefound事件还没触发,所以看不到日志。等安装完成后,新SW进入waiting状态,第二次刷新页面时,代码直接检测到reg.waiting就触发了提示。
如果想触发这个事件的日志,可以在修改SW后,先打开DevTools的Application面板手动点击“更新”,或者在页面注册SW后等待几秒,让异步的更新检查完成,就能看到updatefound的打印。
2. reg.installing 检查(“更新进行中”)
这个检查是为了捕获页面加载时,已经有一个SW处于安装阶段的场景,比如:
- 用户打开页面时,之前的某个标签页已经触发了SW更新,且安装还在进行中
- 浏览器后台自动更新SW(比如设置了定期检查),刚好在页面加载时处于安装状态
你的测试流程里,每次修改后立刻刷新,安装过程很快完成,页面加载时reg.installing已经不存在了,所以不会触发这个分支。
3. reg.waiting 检查(“已有等待安装的更新”)
这就是你测试到的场景:新SW已经完成安装,但因为当前页面还在使用旧的激活SW,新SW会进入waiting状态,等待所有被旧SW控制的页面关闭后才能激活。第二次刷新页面时,代码检测到这个等待的SW,触发更新提示。
三个检查是否必要?
是的,三个检查覆盖了所有可能的更新状态,缺一不可:
updatefound:监听未来可能发生的更新,确保新SW开始安装时能跟踪进度,安装完成后及时提示用户reg.installing:处理页面加载时已经在进行的安装,避免错过正在进行的更新reg.waiting:处理已经完成安装、等待激活的更新,让用户及时知道有可用更新
如果缺少任何一个,都会导致某些更新场景下无法给用户正确的提示。
内容的提问来源于stack exchange,提问作者aderchox

