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

React JS PWA中Service Worker推送通知无响应问题求助

问题分析与修复方案

看了你的代码,发现几个关键问题导致Service Worker的install/activate事件没触发、推送功能完全失效,咱们一步步来解决:


1. 最核心的问题:Service Worker注册逻辑根本没执行

你的index.js里只写了serviceWorker.register(),但worker.js中的register函数是导出的模块,如果index.js没有正确导入这个函数,注册逻辑等于没跑!这就是为什么控制台连register called都没输出的原因。

2. Service Worker全局对象用错了

Service Worker运行在独立的后台上下文里,没有window这个对象!你代码里的window.self、window.registration全是错误的引用——SW里的全局对象是self,所有事件绑定、API调用都得基于它。

3. Activate事件没等待异步操作完成

你在activate事件里直接调用了pushManager.subscribe这个异步操作,但没把它放进event.waitUntil()里。这会导致事件在订阅请求完成前就结束,订阅逻辑直接被中断,后续自然收不到推送。

4. 额外的细节问题

  • 旧的Service Worker可能还缓存着,导致新代码不生效,需要加skipWaiting()强制激活新SW
  • urlBase64ToUint8Array里的window.atob也要改成self.atob,SW里没有window

修改后的完整代码

index.js(确保正确导入并调用注册函数)

// 先导入worker里的注册函数
import { register } from './worker.js';

// 调用注册逻辑
register();

worker.js(修复所有错误点)

const publicVapidKey = "BOdud_KdO16dL40D56LbksLa6ElXFAJu-2XEdIKQUmehzomo6FES2jJ1niaUYrCobfI8U5rkqeQNjPB03mKZMvY";

export const register = () => {
  console.log('register called');
  if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register('/worker.js')
      .then((responseRegister) => {
        console.log('register object', responseRegister);
        window.registration = responseRegister;
      })
      .catch((err) => {
        console.log('error is ', err);
      });
  }
};

export const unregister = () => {
  console.log("unregister called");
  if ('serviceWorker' in navigator) {
    navigator.serviceWorker.getRegistrations()
      .then(function (registrations) {
        console.log('registrations', registrations);
        for (let registration of registrations) {
          registration.unregister();
        }
      }).catch(function (err) {
        console.log('Service Worker registration failed: ', err);
      });
  }
};

// 修复:用self绑定install事件,添加skipWaiting强制激活新SW
self.addEventListener('install', (event) => {
  console.log('service worker installed', event);
  event.waitUntil(self.skipWaiting());
});

// 修复:用self绑定activate事件,用waitUntil包裹异步订阅逻辑
self.addEventListener('activate', (event) => {
  console.log('service worker activated', event);
  // 让SW控制所有打开的页面
  event.waitUntil(self.clients.claim());
  
  // 把订阅逻辑放进waitUntil,确保事件等待异步操作完成
  event.waitUntil(
    self.registration.pushManager.subscribe({
      userVisibleOnly: true,
      applicationServerKey: urlBase64ToUint8Array(publicVapidKey)
    }).then((subscription) => {
      console.log('subscription', subscription);
    }).catch((err) => {
      console.log('error in subscribing to push', err);
    })
  );
});

// 修复:用self绑定push事件,用self.registration显示通知
self.addEventListener("push", (e) => {
  const data = e.data.json();
  console.log("Push Recieved...");
  self.registration.showNotification(
    data.title,
    {
      body: "Notified by Traversy Media!",
    }
  );
});

function urlBase64ToUint8Array(base64String) {
  const padding = "=".repeat((4 - base64String.length % 4) % 4);
  const base64 = (base64String + padding)
    .replace(/\-/g, "+")
    .replace(/_/g, "/");
  const rawData = self.atob(base64); // SW里用self.atob替代window.atob
  const outputArray = new Uint8Array(rawData.length);
  for (let i = 0; i < rawData.length; ++i) {
    outputArray[i] = rawData.charCodeAt(i);
  }
  return outputArray;
}

测试步骤

  1. 打开Chrome DevTools的Application > Service Workers面板,勾选Update on reload,确保每次刷新都加载最新的SW
  2. 刷新页面后,检查面板里是否能看到你的worker.js,状态应为activated
  3. 测试推送前,确认你的VAPID公钥和后端私钥匹配,且后端推送请求的格式正确
  4. 注意:只有HTTPS环境(localhost除外)才能正常使用推送功能

内容的提问来源于stack exchange,提问作者ash1102

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 17:18:13