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

仅当标签页关闭时显示推送通知的功能不生效如何解决?

问题原因

你当前的实现存在4个核心问题,导致逻辑不生效:

  • Service Worker是事件驱动的短命进程,浏览器会在空闲时自动回收SW实例,你声明在全局的allowed变量属于内存临时存储,SW被回收后值会被重置,之前接收的start/stop状态会完全丢失。
  • sw.js中allowed变量没有设置初始值,初始状态为undefined,如果SW是被推送事件唤醒、此前没有收到过任何页面发来的消息,判断逻辑会完全失效。
  • 页面中postMessage的执行时机错误:subscribe是异步函数,Service Worker注册是异步过程,你在window.onload中同步调用navigator.serviceWorker.controller.postMessage时,大概率controller还未初始化完成(值为null),消息根本没有发送到SW。
  • onbeforeunload事件触发不可靠,页面崩溃、浏览器强制杀进程等场景下不会触发,会导致状态永久错误。
最优修复方案

不需要手动维护start/stop状态,直接在SW的推送事件中查询当前是否有活跃的页面窗口即可,完全规避状态丢失问题,实现更稳定:
你可以直接把sw.js替换为以下代码,同时删除main.js中所有和postMessage相关的代码即可:

self.addEventListener('push', event => {
    event.waitUntil(
        // 查询所有当前受SW控制的窗口客户端
        self.clients.matchAll({
            type: 'window',
            includeUncontrolled: false
        }).then(clientsList => {
            // 存在可见的活跃窗口时不弹出通知
            const hasActiveWindow = clientsList.some(client => client.visibilityState === 'visible');
            if (!hasActiveWindow) {
                const data = event.data.json();
                return self.registration.showNotification(data.title, {
                    body: data.body,
                    icon: data.icon
                });
            }
        })
    );
});
原有逻辑的修复方案(不推荐)

如果你坚持要用原有消息通信的方案,需要做以下修改:

  1. 把allowed状态存储到IndexedDB或Cache Storage等持久化存储中,不要存在全局变量
  2. 把postMessage逻辑挪到Service Worker注册完成的回调中执行,确保消息能送达
  3. 给allowed设置默认初始值true,默认允许未打开页面时推送通知

内容的提问来源于stack exchange,提问作者Adi B.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 14:15:03