配了三年 Web Push,每次在 Notification.requestPermission() 里拿 granted 就直接调订阅接口——今天 Chrome 155 把这件事从根上变了

配了三年 Web Push,每次在 Notification.requestPermission() 里拿 granted 就直接调订阅接口——今天 Chrome 155 把这件事从根上变了。

Chrome 155 for Android 带了一个非阻塞通知权限 prompt:用户可以无视弹窗,窗口自动消失。但这个看似“更好用”的改动背后,有个坑你没注意——超时返回的状态值变了。

旧逻辑: 弹窗被用户无视或关掉,Notification.requestPermission() resolve 为 denied。开发者看到这个值,知道“没戏了”,直接展示引导用户去设置的提示。

新逻辑: 弹窗自动超时后,Notification.requestPermission() resolve 为 default——意思是“还没决定”。这意味着你的老代码看到 default 可能会再弹一次 prompt,或者以为没权限就放弃了,而不是等待用户从 Site Controls 里打开。

还有一个你没覆盖的路径:用户可以在网站控件菜单里随时订阅通知,不需要再碰原 prompt。这意味着权限状态可能在你没调用 requestPermission() 的情况下变成 granted。你原来的代码如果只在 Promise resolve 后调订阅接口,这个异步状态变化就被漏掉了。

// ❌ 旧写法——超时后拿到 default,你可能以为没权限就放弃了
Notification.requestPermission().then((permission) => {
  if (permission === 'granted') {
    subscribeToPushNotifications();
  }
});

// ✅ 新写法——补上 Site Controls 的异步订阅路径
navigator.permissions.query({ name: 'notifications' })
  .then((permissionStatus) => {
    if (permissionStatus.state === 'granted') {
      subscribeToPushNotifications();
    }
    // 用户从 Site Controls 打开通知权限会触发这个
    permissionStatus.onchange = () => {
      if (permissionStatus.state === 'granted') {
        subscribeToPushNotifications();
      }
    };
  });

Chrome 这次改的真正意图是让你按情境请求通知权限:电子商务在用户下单后请求,新闻网站在用户读了几篇后提示,旅游网站在用户搜完航班后建议。不是页面一加载就弹。

怎么迁:

  1. 把权限检查换成 navigator.permissions.query()
  2. 加 onchange 监听 Site Controls 的异步授权
  3. 把请求时机绑到真实用户行为上,而不是 load 事件
  4. 旧的 Notification.requestPermission().then() 保留,但去掉“没拿到 granted 就展示设置引导”的逻辑——default 现在只是“还没决定”,不是“拒绝了”

这件事本质是浏览器在把通知权限从“一次决定”变成“随时可改”的状态流,你的代码也得跟着从“请求-响应”模型切换到“订阅-监听”模型。

评论区

0 条评论

登录后可评论。

阿柯·前端架构 1310 阅读