使用 Service Worker 发出通知的计时器

Jak*_*Kus 5 javascript timer settimeout service-worker

我想创建一个计时器,它会在点击通知时开始倒计时。

只要中断长度小于一分钟,我的示例就可以很好地工作。当中断长度超过一分钟时,service worker 停止工作。

索引.html

<!DOCTYPE html>
<html>
<body>
<button onclick="notify();">notify</button>
</body>
<script>
  function notify() {
    const items = ["First", "End of the break", "Second"];
    const options = { data: items };

    if ('serviceWorker' in navigator) {
      Notification.requestPermission()
        .then(() => navigator.serviceWorker.register('sw.js'))
        .then(() => navigator.serviceWorker.ready
        .then((s) => {
          s.showNotification('Click to begin', options);
        }))
      .catch(e => console.log(e.message));
    }
  }
</script>
</html>
Run Code Online (Sandbox Code Playgroud)

sw.js

let data = [];
let num = 0;

self.onnotificationclick = (event) => {
  event.notification.close();
  if (event.notification.data) {
    ({ data } = event.notification);
  }

  if (num < data.length) {
    setTimeout(() => {
      self.registration.showNotification(data[num]);
      num += 1;
    }, num % 2 === 0 ? 1 : 3000);
  }
};
Run Code Online (Sandbox Code Playgroud)

我知道应该没有setTimeoutin sw.js,但它最接近我想要达到的目标。

有没有办法建立一个计时器,当您单击通知时开始倒计时并通知您倒计时结束?

Mat*_*unt 6

(这是一个很长的答案,因为有一些事情可以与您的问题讨论)

Service Worker 的设计方式是您应该尽快完成工作并将控制权返回给浏览器。这是通过以下event.waitUntil(<promise>)函数完成的:您通过不解析传入的承诺来告诉浏览器您正忙。

在上面的示例中,您没有使用event.waitUntil()可以延长服务人员寿命的方法。

例如,您可以尝试:

self.onnotificationclick = (event) => {
  event.notification.close();
  if (event.notification.data) {
    ({ data } = event.notification);
  }

  if (num < data.length) {
    event.waitUntil(new Promise(function(resolve, reject) {
        setTimeout(() => {
            self.registration.showNotification(data.num);
            resolve();
        }, 3000);
    })
  }
};
Run Code Online (Sandbox Code Playgroud)

但是,如果您设置的超时被认为太长(并且由浏览器决定太长的超时),则浏览器可以终止 Service Worker,从而给用户带来不可预测的体验。

这是因为您的预期用例通常不是 Service Worker API 的设计目的。有人提出了替代 API 的建议,但没有一个得到关注(或者至少据我所知 - 尽管这已经有一段时间了)。

另请注意:在 Service Worker 中使用全局变量应谨慎使用。正如我所说,Service Worker 可以频繁启动和终止,因此从 IndexDB 读取/写入可能更适合存储信息。


Ser*_*ndt 6

通知触发API

对于较长持续时间的计时器,目前(2021 年 4 月)正在通知触发器 API上完成工作。

Google 开发人员的评论可以作为问题留在专用的 GitHub 存储库中。

Chrome M80-M83 Origin 试用版的反馈也已提供。

目前,需要设置标志#enable-experimental-web-platform-features才能chrome://flags使其工作。一旦这个 API 变得稳定并成为主流,我将用代码更新这个答案。

最后,这篇有关 Service Worker 中任务调度的精彩概述中有更多示例和测试。这还涉及定期后台同步 API。

  • 这个已经停产了 (2认同)