为什么 setInterval() 在此代码中过早停止?

Why does setInterval() stop too early in this code?

<div class="wait">Wait</div>
<div class="waitDownloadLink"></div>

$(document).ready(function()
                  {
                      var secondNormal = 40;
                      var refreshIntervalId;
                      refreshIntervalId = setInterval(function() {
                          secondNormal -= 1;
                          $(".wait").text(secondNormal);

                      }, 1000); 
                      setTimeout(function() {
                          clearInterval(refreshIntervalId);
                          $(".waitDownloadLink").text("Click me to download");
                      }, secondNormal * 1000);




                  });

当我开始 运行 代码并停留在网页上时,代码似乎工作得非常完美(或接近)。但是,当我在启动代码后立即在其他网页上冲浪时,计时器停留在 12 - 18 秒之间然后停止 运行。为什么会这样?有什么办法可以解决这个问题吗?

https://jsfiddle.net/s1zf18co/

浏览器通常会在不可见的选项卡中暂停或降低 Javascript 运行 的线程优先级。我的猜测是,这是笔记本电脑和其他设备的一种节能措施,但他们多年来一直这样做。 This question 对该问题进行了令人难以置信的彻底调查。

解决方案是使用不会暂停的网络工作者。有关详细信息,请参阅 the Mozilla documentation

有一个可行的解决方案,试试这个和 c 如果它足够好,离开页面问题没问题,在结束条件下编辑。

$(document).ready(function () {
    var secondNormal = 40;

    var refreshIntervalId = setInterval(function () {
        setTimeout(function () {
            if(secondNormal >0) {
                secondNormal -= 1;
            }
        }, 1000)

        $(".wait").text(secondNormal);
    }, 1000);
});

除了莫德雷德的回答,在这种情况下,您可以尝试使用 JS Date 对象来正确估计时间。查看 this question

我似乎无法复制该错误,但我相信使用 Date 对象可能会修复它:

var getDateTimeInSeconds = function() {
  return Math.floor(Date.now() / 1000)
};

$(document).ready(function() {
  var numOfSeconds = 40;
  var countFrom = getDateTimeInSeconds();
  var countTo = countFrom + numOfSeconds;

  var refreshIntervalId = setInterval(function() {
    var secondsLeft = countTo - getDateTimeInSeconds();
    if (secondsLeft < 0) {
      $(".wait").text(0);
      $(".waitDownloadLink").text("Click me to download");
      clearInterval(refreshIntervalId);
    } else {
      $(".wait").text(secondsLeft);
    }
  }, 1000);

});

Fiddle: https://jsfiddle.net/s1zf18co/1/