使用Service Worker进行通知的计时器

时间:2018-11-06 19:27:38

标签: javascript timer settimeout service-worker

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

只要中断时间少于一分钟,我的样本就可以很好地工作。 如果休息时间超过一分钟,服务人员将停止工作。

index.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>

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);
  }
};

我知道setTimeout中不应有sw.js,但这是我想要达到的最接近的点。

是否可以构建一种计时器,当您单击通知时,该计时器开始倒计时并通知您倒数结束?

2 个答案:

答案 0 :(得分:1)

(这是一个很长的答案,因为有一些问题需要讨论)

服务工作者的设计方式是,您应该尽快完成工作并将控制权返回给浏览器。这是通过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);
    })
  }
};

但是,如果您设置的超时时间过长(由浏览器决定是否太长),浏览器可以终止服务工作者,从而导致无法预期的体验您的用户。

这是因为您的预期用例通常不是服务工作者API设计的目的。有替代API的建议,但没有一个吸引人(或者至少我不知道-尽管那是一段时光)。

另一个注意事项:在服务工作者中使用全局变量时应格外小心。就像我说的那样,服务人员可以频繁启动和终止,因此从indexDB进行读/写操作可能更适合于存储信息。

答案 1 :(得分:1)

通知触发器 API

关于更长持续时间的计时器,目前(2021 年 4 月)正在 Notification Trigger API 上完成工作。

对 Google 开发者的评论可以作为问题留在 dedicated GitHub repository 中。

Feedback 来自 Chrome M80-M83 Origin 试用版。

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

最后,这个优秀的overview about task scheduling in the service worker还有更多的例子和测试。这也涉及到定期后台同步 API。