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

Chrome中navigator.serviceWorker.ready Promise始终无法resolve,Edge/Opera正常运行、Firefox报错

Chrome中navigator.serviceWorker.ready Promise始终无法resolve,Edge/Opera正常运行、Firefox报错

看起来你碰到了一个挺棘手的Service Worker兼容性问题,我之前也遇到过类似的情况,先帮你梳理下可能的原因和解决思路:

先排查Service Worker的核心状态

Chrome里navigator.serviceWorker.ready迟迟不resolve,大概率是你的Service Worker没走完安装→激活的完整流程。你可以打开Chrome DevTools的Application标签页,找到Service Workers面板,看看SW的状态:

  • 如果一直卡在installing:说明安装阶段出了问题,最常见的就是cache.addAll里的资源加载失败(比如404、跨域或加载超时)
  • 如果停在waiting:说明新SW安装好了,但旧SW还在控制页面,没被替换掉

检查Service Worker代码里的潜在坑

看你的SW代码,有几个容易踩的点:

  1. cache.addAll的错误捕获不完整
    你在install事件里加了try/catch,但e.waitUntil里的cache.addAll是异步操作,一旦某个资源加载失败,这个Promise会直接reject,而外层的try/catch捕获不到这个异步错误,会导致SW安装失败。可以改成async/await写法,把整个逻辑包在try里:
self.addEventListener('install', async (e) => {
    try {
        const cache = await caches.open(CACHE_NAME);
        await cache.addAll([
            '/Vanilla/test_sg9.html',
            '/Vanilla/Scales.png',
            // 其他资源...
        ]);
        await self.skipWaiting();
        console.log("SW安装完成");
    } catch(err) {
        console.error('SW安装失败:', err);
    }
    console.log("Leaving install");
})
  1. self.skipWaiting()的执行时机
    你现在是在cache.addAll的then回调里调用skipWaiting(),如果cache.addAll失败,这步就不会执行,新SW会一直处于waiting状态,无法激活,自然ready就不会触发。用async/await写法能更清晰地控制执行顺序。

  2. activate事件里的多个e.waitUntil
    你在activate事件里调用了两次e.waitUntil,这可能导致逻辑冲突,建议把两个Promise合并成一个:

self.addEventListener('activate', (e) => {
    e.waitUntil(
        Promise.all([
            // 清理旧缓存
            caches.keys().then((keyList) => {
                return Promise.all(keyList.map((key) => {
                    if (key !== CACHE_NAME) {
                        console.log('Removing cache', key);
                        return caches.delete(key);
                    }
                }))
            }),
            // 立即控制所有打开的页面
            self.clients.claim()
        ])
    )
})

关于Firefox的异常

Firefox对module类型的Service Worker处理逻辑更严格,你可以打开Firefox的控制台看具体错误信息,大概率是模块导入(比如/Vanilla/config.js)或资源加载的问题。

临时兜底方案(如果暂时无法修复激活问题)

你提到的SO workaround确实可以作为临时方案,通过监听controllerchange事件来兜底:

if ("serviceWorker" in navigator) {                 
    const reg = await navigator.serviceWorker.register('/Vanilla/CacheManager.js', { scope: '/Vanilla/', type: 'module' })
        .catch(err => console.log('SW Registration failed with ' + err));
    
    // 检查是否已有激活的SW
    if (navigator.serviceWorker.controller) {
        cacheManagerSubscription = await navigator.serviceWorker.ready;
    } else {
        // 等待controller变化
        await new Promise(resolve => {
            navigator.serviceWorker.addEventListener('controllerchange', resolve);
        });
        cacheManagerSubscription = await navigator.serviceWorker.ready;
    }
}

不过这只是权宜之计,还是建议从根源上解决SW的安装激活问题。

额外小建议

  • 每次修改SW代码后,在Chrome DevTools的Service Workers面板勾选Update on reload,强制刷新SW
  • 检查所有缓存资源的路径是否正确,服务器环境下可能区分大小写
  • 确认/Vanilla/config.js能正常加载,module类型的SW导入失败会直接导致SW无法运行

备注:内容来源于stack exchange,提问作者McMurphy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.13 19:34:29