考虑以下代码:

var tick = 0;

setInterval(() => {
    console.log(tick);
}, 1000);

setInterval(() => {
  tick += 1;
}, 1);


基本上,我希望游戏看起来平滑,因此我每1毫秒更新一次点的位置,第二个setInterval中的函数会这样做。

在1秒(即1000毫秒)中,我希望点已移动1000像素。但是,它移动大约250个像素。

当我运行以下jsfiddle时,我看到大约250的倍数被打印到控制台。

https://jsfiddle.net/58v74zw4/1/

根据我的观察,我可以通过乘以4来修复它,但是感觉很棘手。

是什么原因造成的,正确的解决方法是什么?

最佳答案

我发现的有关JS计时器的最佳文章:https://johnresig.com/blog/how-javascript-timers-work


  由于JavaScript在异步事件发生时一次只能执行一段代码,因此排队等待稍后执行。


这意味着,如果有大量的代码正在执行4ms,则间隔处理程序最多排队等待4ms。

 ms | event
----|--------------------------------------------
  0 | bigChunk() starts
  1 |
  2 | interval event fires
  3 |
  4 | bigChunk() returns
  5 | interval handler starts



  浏览器一直等到没有更多的间隔处理程序排队之后才开始排队。


这意味着,如果有大量代码正在执行4ms,并且如果将间隔设置为每1ms触发一次,则浏览器将在4ms之后执行第一个间隔处理程序并丢弃3个事件。

 ms | event
----|--------------------------------------------
  0 | bigChunk() starts
  1 | interval event fires
  2 | interval event dropped
  3 | interval event dropped
  4 | interval event dropped, bigChunk() returns
  5 | interval handler starts


在您的情况下,由于这个原因可能会丢失3/4(750/1000)个间隔事件,但是也有与实现相关的原因,例如在此所述的连续调用之间的最小延迟为4ms,此处描述为:https://stackoverflow.com/a/9647221/1636522(信用:)。

如您所见,setInterval在单线程中使用时并不可靠,但是,多线程并不一定会使事情变得容易。例如,如果间隔处理程序的执行时间为4毫秒,则将需要4个线程,每个线程之间的时移为1毫秒。

 Thread 1                      | Thread 2
-------------------------------|-------------------------------
 ms | event                    | ms | event
----|--------------------------|----|--------------------------
  0 | interval event fires     |  0 |
  1 | interval handler starts  |  1 | interval event fires
  2 |                          |  2 | interval handler starts
  3 |                          |  3 |
  4 | interval handler returns |  4 |
  5 |                          |  5 | interval handler returns


这只是要解决的潜在问题之一。就是说,如果您仍然想使用多线程,可以看一下Web Workers。但我还是帮不上忙,我从未使用过此功能:-|
LGSon

还请记住,“大多数浏览器的帧速率为60fps [每秒帧]”(请参阅​​https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers),这意味着您有大约17ms(1000/60)的时间来计算下一帧。因此,每毫秒更新游戏状态可能会过分:-)

关于javascript - setInterval不正确的解决方法是什么?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/49344671/

10-12 14:04