You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 04:31:32