多显示器下 `document.hidden` 判断失效,推送全挂了
写 ShelfTalk 的推送系统时,我想着用户正盯着网页聊天,桌面再弹个一模一样的通知多烦人。于是加了个「优化」:
MDN 文档写得明明白白:
现在 ShelfTalk 可能在你盯着屏幕时也会响一下,但至少永远不会漏。🔔
下一篇
第一个站点到期前四天,我才发现源码根本不存在 →
export const sendPushNotification = (title, options = {}, requireHidden = false) => {
if (!('Notification' in window)) return;
if (Notification.permission === 'granted') {
if (requireHidden && !document.hidden) {
return; // 以为用户在看,就不发了
}
// ...发送通知
}
};本地单显示器测全过,上线后用户反馈:完全收不到推送。
document.hidden === false 只代表「操作系统能看见窗口」,不代表「人在看」。
- 双显示器:ShelfTalk 挂副屏,主屏干别的,
document.hidden依然false,通知被吞 - 公司电脑没关浏览器,回家打开笔记本,公司那台「可见」,家里这台也收不到
- 平板支在桌上跑着网页,人早走了,OS 觉得可见,推送照样不发
MDN 文档写得明明白白:
document.hidden 只管页面可见性状态,跟人类注意力没关系。我却把布尔值强行赋予了「用户正在注视」的含义。修法:直接删掉那段「聪明」代码
- if (requireHidden && !document.hidden) {
- return;
- }
+ // 通知照常发,哪怕标签页可见
+ // 保证多设备、多显示器场景都能触达提交记录:b0c9b1645b4543e48778fea7137cdf5d4761b10e
三个教训
- 别只在自己的开发机上测:单显示器根本复现不了,真实环境全是多屏、多设备、后台挂着
- API 语义别脑补:
document.hidden是给 OS 看的,不是给人看的 - 宁可重复提醒,别静默丢消息:多响一次顶多烦人,漏掉一条才是把核心功能搞坏了
现在 ShelfTalk 可能在你盯着屏幕时也会响一下,但至少永远不会漏。🔔
免费 AI 工具箱 · 全部完全免费

后来改用 IntersectionObserver + mousemove/keydown 组合,再加个心跳包,才勉强算「真在看」