使用 service worker 的带有通知的计时器
Timer with notifications using service worker
我想创建一个计时器,在点击通知时开始倒计时。
只要中断时间少于一分钟,我的示例就可以正常运行。
当中断时间超过一分钟时,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);
}
};
我知道sw.js
中不应该有setTimeout
,但它是最接近我想要达到的点。
有没有办法构建一个计时器,当您单击通知时开始倒计时并通知您倒计时结束?
(这是一个很长的答案,因为有一些事情要与您的问题讨论)
Service Worker 的设计方式是您应该尽快完成工作并将控制权 return 交给浏览器。这是通过 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);
})
}
};
但是如果您设置的超时被认为太长(并且由浏览器决定什么太长),浏览器可以终止 service worker,从而导致为您的用户带来不可预测的体验。
这是因为您的预期用例通常不是 service worker API 的设计目的。有替代 API 的建议,但没有一个获得牵引力(或者至少我不知道 - 尽管那是一段时间了)。
另请注意:在服务工作者中使用全局变量应谨慎使用。正如我所说,Service Worker 可以频繁启动和终止,因此从 indexDB 读取/写入可能更适合存储信息。
通知触发器API
关于持续时间更长的计时器,目前(2021 年 4 月)正在 Notification Trigger API 上完成工作。
Google 开发人员的评论可以作为问题留在 dedicated GitHub repository。
Feedback 来自 Chrome M80-M83 Origin Trial 也可用。
目前,需要在 chrome://flags
中设置 #enable-experimental-web-platform-features
标志才能正常工作。一旦这个 API 变得稳定和主流,我将用代码更新这个答案。
最后,在这个优秀的overview about task scheduling in the service worker中有更多的例子和测试。这也涉及定期后台同步 API.
我想创建一个计时器,在点击通知时开始倒计时。
只要中断时间少于一分钟,我的示例就可以正常运行。 当中断时间超过一分钟时,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);
}
};
我知道sw.js
中不应该有setTimeout
,但它是最接近我想要达到的点。
有没有办法构建一个计时器,当您单击通知时开始倒计时并通知您倒计时结束?
(这是一个很长的答案,因为有一些事情要与您的问题讨论)
Service Worker 的设计方式是您应该尽快完成工作并将控制权 return 交给浏览器。这是通过 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);
})
}
};
但是如果您设置的超时被认为太长(并且由浏览器决定什么太长),浏览器可以终止 service worker,从而导致为您的用户带来不可预测的体验。
这是因为您的预期用例通常不是 service worker API 的设计目的。有替代 API 的建议,但没有一个获得牵引力(或者至少我不知道 - 尽管那是一段时间了)。
另请注意:在服务工作者中使用全局变量应谨慎使用。正如我所说,Service Worker 可以频繁启动和终止,因此从 indexDB 读取/写入可能更适合存储信息。
通知触发器API
关于持续时间更长的计时器,目前(2021 年 4 月)正在 Notification Trigger API 上完成工作。
Google 开发人员的评论可以作为问题留在 dedicated GitHub repository。
Feedback 来自 Chrome M80-M83 Origin Trial 也可用。
目前,需要在 chrome://flags
中设置 #enable-experimental-web-platform-features
标志才能正常工作。一旦这个 API 变得稳定和主流,我将用代码更新这个答案。
最后,在这个优秀的overview about task scheduling in the service worker中有更多的例子和测试。这也涉及定期后台同步 API.