我正在制作一个Firefox浏览器扩展(注意:Chrome扩展和Firefox扩展有非常相似的api ),它可以监控用户可以选择的某些网站的屏幕时间。具体来说,屏幕时间计数器应该每24小时在午夜复位一次.
所讨论的代码:
let interval = setInterval(update, 1000);
let msTillMidnight = (new Date().setHours(24, 0, 0, 0) - Date.now());
function restart() {
browser.storage.local.get("totalTime").then(res => {
browser.storage.local.set({timeLeft: res["totalTime"]});
});
if (!running) {
running = true;
interval = setInterval(update, 1000);
}
}
new Promise(resolve => setTimeout(resolve, msTillMidnight)).then(() => { // I am aware this is laughably redundant, but in theory it should work exactly the same
restart();
setInterval(restart, 1000 * 60 * 60 * 24); // 1000 ms/second —> 60 s/minute —> 60 m/hour —> 24 h/day
});
我注意到一个非常奇怪的行为。在分机开始运行后的第一个午夜之后,没有调用restart
。没有更新浏览器存储变量,也没有更新间隔,也没有更新running
bool。问题,我认为,是setTimeout
问题是根本没有运行。然而,第二天晚上,时钟已经重置
msTillMidnight
变量有问题吗?这是因为后台页面关闭,不会运行任何setTimeout
脚本一段时间后,当我的计算机在午夜睡觉,restart
函数只会调用当我的计算机还在或最近关闭?或者,可能是我的多余代码行绕圈子而不是简单的setTimeout导致了错误?我很想自己调试这个,但是我的测试周期很可能是24小时,这比我希望的要慢一点…
setTimeout
和setInterval
不依赖于计算机时钟。它们是计时器,所以如果浏览器"丢失"当计算机处于休眠状态时,定时器在此时间内不会提前。
您需要使用setInterval
并每nn秒检查日期。但是,如果挂起扩展,此操作也可能失败。
一个更好的方法可能是使用警报代替。具体来说,通过在alarmInfo
选项中使用when
。然而,警报将"迎头赶上"。如果错过了(例如在你的情况下,如果电脑已经睡了7天,当它被唤醒时,它会触发7个警报一次)
这应该与manifest v2工作得很好,但是manifest v3没有后台进程,它在15分钟左右后暂停扩展,甚至警报也不会触发。有一些方法可以解决这个问题,但没有一个是完美的。
好的,如果将来有人在看这个。是的,我修好了。更具体地说,vanowm的答案对我有效。
虽然,由于某些原因,本地alarm
实现不工作,所以我自己做了一个仍然可以工作的。