Javascript 什么';设置间隔不准确的修复方法是什么?

Javascript 什么';设置间隔不准确的修复方法是什么?,javascript,Javascript,考虑以下代码: var tick = 0; setInterval(() => { console.log(tick); }, 1000); setInterval(() => { tick += 1; }, 1); 基本上,我希望我的游戏看起来平滑,所以我每1毫秒更新一次点的位置,第二个setInterval中的函数就是这样做的 在1秒或1000毫秒内,我预计圆点移动了1000个像素。但是,它移动大约250像素 当我运行下面的jsfiddle时,我看到控制台上打印

考虑以下代码:

var tick = 0;

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

setInterval(() => {
  tick += 1;
}, 1);
基本上,我希望我的游戏看起来平滑,所以我每1毫秒更新一次点的位置,第二个setInterval中的函数就是这样做的

在1秒或1000毫秒内,我预计圆点移动了1000个像素。但是,它移动大约250像素

当我运行下面的
jsfiddle
时,我看到控制台上打印了大约250的倍数

根据我的观察,我可以通过乘以4来修复它,但它感觉很粗糙


是什么导致了这种情况,正确的解决方法是什么?

我找到的关于JS定时器的最佳文章:

由于JavaScript每次只能执行一段代码[…]当异步事件发生[…]时,它会排队等待稍后执行[…]

这意味着,如果有一大块代码正在执行4ms,则间隔处理程序最多会排队4ms

ms |事件
----|--------------------------------------------
0 | bigChunk()开始
1 |
2 |间隔事件火灾
3 |
4 | bigcunk()返回
5 |间隔处理程序启动
[…]浏览器[…]等待,直到没有更多的间隔处理程序排队[…],然后再排队

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

ms |事件
----|--------------------------------------------
0 | bigChunk()开始
1 |间隔事件火灾
2 |中断事件
3 |中断事件
4 |已删除间隔事件,bigChunk()返回
5 |间隔处理程序启动
在您的情况下,3/4(750/1000)的间隔事件可能会因为这个原因而被丢弃,但也有与实现相关的原因,比如这里描述的连续调用之间4ms的最小延迟:(credits:)

正如您所看到的,
setInterval
在单线程中使用时不可靠,但是,多线程并不一定能让事情变得更简单。例如,如果间隔处理程序的执行时间为4ms,则需要4个线程,每个线程之间的时间偏移为1ms

螺纹1 |螺纹2
-------------------------------|-------------------------------
ms |事件| ms |事件
----|--------------------------|----|--------------------------
0 |间隔事件触发| 0 |
1 |间隔处理程序启动| 1 |间隔事件激发
2 | | 2 |间隔处理程序启动
3 |                          |  3 |
4 |间隔处理程序返回| 4|
5 | | 5 |间隔处理程序返回
这只是需要解决的潜在问题之一。也就是说,如果您仍然想使用多线程,您可以看看Web Workers。不过我还是忍不住,我从未使用过这个功能:-|


还请记住,“大多数浏览器的每秒帧数为60fps”(请参阅),这意味着您有将近17ms(1000/60)的时间来计算下一帧。因此,每毫秒更新一次游戏状态可能有些过分:-)

我找到的关于JS定时器的最佳文章:

由于JavaScript每次只能执行一段代码[…]当异步事件发生[…]时,它会排队等待稍后执行[…]

这意味着,如果有一大块代码正在执行4ms,则间隔处理程序最多会排队4ms

ms |事件
----|--------------------------------------------
0 | bigChunk()开始
1 |
2 |间隔事件火灾
3 |
4 | bigcunk()返回
5 |间隔处理程序启动
[…]浏览器[…]等待,直到没有更多的间隔处理程序排队[…],然后再排队

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

ms |事件
----|--------------------------------------------
0 | bigChunk()开始
1 |间隔事件火灾
2 |中断事件
3 |中断事件
4 |已删除间隔事件,bigChunk()返回
5 |间隔处理程序启动
在您的情况下,3/4(750/1000)的间隔事件可能会因为这个原因而被丢弃,但也有与实现相关的原因,比如这里描述的连续调用之间4ms的最小延迟:(credits:)

正如您所看到的,
setInterval
在单线程中使用时不可靠,但是,多线程并不一定能让事情变得更简单。例如,如果间隔处理程序的执行时间为4ms,则需要4个线程,每个线程之间的时间偏移为1ms

螺纹1 |螺纹2
-------------------------------|-------------------------------
ms |事件| ms |事件
----|--------------------------|----|--------------------------
0 |间隔事件触发| 0 |
1 |间隔处理程序启动| 1 |间隔事件激发
2 | | 2 |间隔处理程序启动
3 |                          |  3 |
4 |间隔处理程序返回| 4|
5 | | 5 |间隔处理程序返回
这只是需要解决的潜在问题之一。也就是说,如果您仍然想使用多线程,您可以看看Web Workers。不过我还是忍不住,我从未使用过这个功能:-|


还请记住,“大多数浏览器的每秒帧数为60fps”(请参阅),这意味着您有将近17ms(1000/60)的时间来计算下一帧。因此,每毫秒更新一次游戏状态可能有点过头了:-)

1对于SetInterval来说似乎太小了。由于大多数浏览者都会重复(1000/60)毫秒的时间间隔