' setTimeout '在Firefox扩展background.js中工作奇怪



我正在制作一个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小时,这比我希望的要慢一点…

setTimeoutsetInterval不依赖于计算机时钟。它们是计时器,所以如果浏览器"丢失"当计算机处于休眠状态时,定时器在此时间内不会提前。

您需要使用setInterval并每nn秒检查日期。但是,如果挂起扩展,此操作也可能失败。

一个更好的方法可能是使用警报代替。具体来说,通过在alarmInfo选项中使用when。然而,警报将"迎头赶上"。如果错过了(例如在你的情况下,如果电脑已经睡了7天,当它被唤醒时,它会触发7个警报一次)

这应该与manifest v2工作得很好,但是manifest v3没有后台进程,它在15分钟左右后暂停扩展,甚至警报也不会触发。有一些方法可以解决这个问题,但没有一个是完美的。

好的,如果将来有人在看这个。是的,我修好了。更具体地说,vanowm的答案对我有效。

虽然,由于某些原因,本地alarm实现不工作,所以我自己做了一个仍然可以工作的。

最新更新