setInterval()没有达到最高速度

时间:2019-05-12 18:03:38

标签: javascript setinterval

我正在我正在工作的网站上制作图库。它会自动滚动浏览照片,但用户也可以暂停并手动滚动。我遇到的问题是自动滚动定时。我做了一个setInterval()每毫秒运行一次autoScroll()。在autoScroll()中,它会增加一个变量,然后滚动,并将变量设置为3000,然后将其设置回0。我这样做是为了代替在直接调用滚动的setInterval上使用3000毫秒,我可以在用户暂停或手动滚动时重置计时器。理论上,它应该每3秒滚动一次。但这要慢得多。在Chrome中,大约需要12秒,在Firefox中大约需要45秒。我尚未在其他任何浏览器上对其进行测试。

当前,我直接在计算机上运行它,因此尚不涉及服务器。因此,应该是代码问题,而不是服务器问题。

以下是脚本引用的相关HTML:

<table>
  <tr>
    <th>
      <button id="left">&#10094;</button>
    </th>
    <th id="picture" colspan="3"></th>
    <th>
      <button id="right">&#10095;</button>
    </th>
  </tr>
  <tr>
    <td></td>
    <td id="pause">&#10074;&#10074;</td>
    <td id="below"><span id="caption" style="text-align: center;"></span><br><span id="dots"
        style="text-align: center;"></span></td>
    <td style="width: 5%"></td>
    <td></td>
  </tr>
</table>

这是javascript:

var pics = ["pic1.jpg", "pic2.jpg", "pic3.jpg", "pic4.jpg", "pic5.jpg"];
var captions = ["caption 1", "caption 2", "caption 3", "caption 4", "caption 5",];
var play = true;
var position = 0;
var direction = 0;
var auto = 0;

for (var x = 1; x < pics.length + 1; x++) {
  dots.innerHTML = dots.innerHTML + '<input id="dot' + x.toString() + '" type="radio" name="dot" value="' + x.toString() + '"><label for="dot' + x.toString() + '">&#9679;</label>';
}

dot1.checked = true;
picture.innerHTML = '<img src="' + pics[0] + '" />';
caption.innerHTML = captions[0];

function move() {
  var positionIndex = position + 1;
  position = position + direction;
  if (position == -1) { position = pics.length - 1; }
  if (position == pics.length) { position = 0; }
  positionIndex = position + 1;
  picture.innerHTML = '<img src="' + pics[position] + '" />';
  caption.innerHTML = captions[position];
  document.getElementById("dot" + positionIndex.toString()).checked = true;
  auto = 0;
}

left.onclick = function () {
  direction = -1;
  move();
}

right.onclick = function () {
  direction = 1;
  move();
}

dots.onclick = function () {
  position = parseInt(document.querySelector('input[name = "dot"]:checked').value) - 1;
  positionIndex = position + 1;
  picture.innerHTML = '<img src="' + pics[position] + '" />';
  caption.innerHTML = captions[position];
  document.getElementById("dot" + positionIndex.toString()).checked = true;
  auto = 0;
}

pause.onclick = function () {
  if (play) {
    play = false;
    pause.innerHTML = "&#9654;";
  } else {
    play = true;
    pause.innerHTML = "&#10074;&#10074;";
  }
  auto = 0;
}

function autoScroll() {
  auto++
  if (auto == 3000 && play) {
    direction = 1;
    auto = 0;
    move();
  }
}

window.setInterval(autoScroll, 1);

1 个答案:

答案 0 :(得分:1)

由于缓解了崩溃/幽灵漏洞,所有浏览器都故意使计时器的精度降低。我不确定setInterval是否被视为高分辨率计时器,但它也可能会受到影响。

https://developers.google.com/web/updates/2018/02/meltdown-spectre

即使在此之前,setInterval也不保证它将在规定的时间后准确触发。如果浏览器很忙,它会变得更糟。

简而言之,您应该检查当前时间(例如,使用+(new Date())),并查看实际经过了多少时间,而不是将每个setInterval的变量增加1。

  ...
  auto = +(new Date());
}
function autoScroll() {
  var date = +(new Date());
  if(auto > date + 3000 && play) {
    direction = 1;
    auto = date;
    move();
  }
}

或者,正如已经建议的那样,放弃使用较短的setInterval的想法,保存对计时器的引用,然后取消该计时器,如果用户单击,则重新启动它。

  ...
  resetTimer();
}
function autoScroll() {
  if(play) {
    direction = 1;
    resetTimer();
    move();
  }
}
function resetTimer() {
   if(timer) {
       window.clearInterval(timer);
   }
   timer = window.setInterval(autoScroll,3000);
}
timer = window.setInterval(autoScroll,3000);