Polymer 2.x如何在service-worker更新可用时显示toast提示
Service Worker更新时显示Toast提示的实现方案
嘿,这个场景我刚好实操过,给你捋个清晰的解决思路,完美避开你提到的两个痛点👇
核心思路
通过Service Worker与主线程的消息通信来实现:SW监听更新事件后给主线程发通知,主线程收到消息后,根据Shell的加载状态决定是立即显示Toast还是先缓存状态,等Shell加载完成再触发。这样既解决了SW注册时Shell未加载的问题,也能优雅使用paper-toast组件。
具体实现步骤
1. 在Service Worker中监听更新并发送消息
在你的service-worker.js里添加以下代码,当新的SW安装完成进入等待激活状态时,给所有打开的页面客户端发送更新通知:
self.addEventListener('waiting', (event) => { // 获取所有当前打开的窗口客户端 self.clients.matchAll({ type: 'window' }).then(clients => { clients.forEach(client => { // 发送自定义消息标记更新事件 client.postMessage({ type: 'SW_UPDATED' }); }); }); });
2. 在主线程处理消息并控制Toast显示
第一步:导入并添加paper-toast组件
在index.html的头部导入组件(确保Web Component环境已就绪),并在页面末尾添加Toast元素:
<!-- index.html 头部导入组件 --> <link rel="import" href="/bower_components/paper-toast/paper-toast.html"> <!-- index.html body末尾添加Toast元素 --> <paper-toast id="updateToast" text="新版本已准备好,刷新页面即可更新!" button-text="刷新" on-click="handleRefresh" ></paper-toast>
第二步:编写主线程消息监听逻辑
在index.html中添加脚本,处理SW的消息,同时兼容Shell未加载的情况:
// 标记Shell是否加载完成 let isShellLoaded = false; // 缓存SW更新通知(如果Shell未加载) let hasPendingUpdate = false; // 监听Service Worker发来的消息 navigator.serviceWorker.addEventListener('message', (event) => { if (event.data.type === 'SW_UPDATED') { if (isShellLoaded) { // Shell已加载,直接显示Toast document.getElementById('updateToast').show(); } else { // Shell未加载,先缓存更新状态 hasPendingUpdate = true; } } }); // 假设你的Shell加载完成后会调用这个函数(根据你的实际情况调整) function onShellReady() { isShellLoaded = true; // 如果之前有缓存的更新通知,现在显示Toast if (hasPendingUpdate) { document.getElementById('updateToast').show(); } } // Toast按钮点击后的刷新逻辑 function handleRefresh() { window.location.reload(); }
3. 完善Service Worker注册的监听
在index.html的SW注册代码中,添加updatefound监听,确保能捕获到SW的更新状态:
if ('serviceWorker' in navigator) { window.addEventListener('load', () => { navigator.serviceWorker.register('/service-worker.js') .then((registration) => { // 监听SW更新事件 registration.addEventListener('updatefound', () => { const newWorker = registration.installing; newWorker.addEventListener('statechange', () => { if (newWorker.state === 'installed') { // 此时新SW已安装,等待激活,上面的waiting事件会触发通知 if (navigator.serviceWorker.controller) { console.log('新版本已准备就绪,等待页面刷新'); } } }); }); }) .catch((error) => { console.error('Service Worker注册失败:', error); }); }); }
针对你提到的两个思路的补充说明
- 调用Shell函数的问题:通过缓存
hasPendingUpdate状态,等Shell加载完成后再触发Toast,完美避开了SW注册时Shell未加载的时序问题; - 导入
paper-toast的问题:直接在index.html中导入组件并添加元素,通过主线程的消息监听控制显示,无需担心组件加载时机的问题。
内容的提问来源于stack exchange,提问作者user2799180
相关产品推荐
相关产品推荐

