setInterval上的计时;看起来不准确

Timing on setInterval doesn't seem accurate

本文关键字:看起来 不准确 setInterval      更新时间:2023-09-26

我正在编写一些javascript来更改当前显示的图像的不透明度,使其看起来变淡,然后将图像更改为其他图像。我将图像更改的setInterval设置为等待5000ms。用于衰落的setInterval被设置为在4000ms处开始。setTimeout被调用10次,全部等待100ms,这弥补了衰落的setInterval在前等待的时间和ChangeImage setInverval在前等待时间之间的差异。

var num, lastNum = 0, count = 10, tcount = 0.0;
var file = "images/image-", ext = ".jpg", image, temp;
var f1 = "alpha(opacity=", f2 = ")";
window.onload = setTimeout(Initialize, 0);
window.onload = setInterval(ImageFader, 4000);
window.onload = setInterval(ChangeImage, 5000);
function Initialize()
{
    image = document.getElementById('title-image');
    image.src = "images/image-1.jpg";
}
function ChangeImage()
{
    image = document.getElementById('title-image');
    do
    {
        num = Math.floor((Math.random() * 10) + 1);
    } while (num == lastNum);
    lastNum = num;
    temp = file.concat(num.toString());
    image.src = temp.concat(ext);
}
function ImageFader()
{
    setTimeout(Fade, 100);
}
function Fade()
{
    tcount = count / 10;
    image.style.opacity = tcount;
    f1 = f1.concat((tcount * 100).toString());
    image.style.filter = f1.concat(f2);
    if (count > 1)
    {
        count--;
        setTimeout(Fade, 100);
    }
    else
    {
        count = 10;
        image.style.opacity = 1;
        image.style.filter = "alpha(opacity=100)";
    }
}

我真的很困惑,为什么时代不匹配。第一个图像的衰落时间安排得很好。在此处,它会淡入淡出,然后在正确的时间移动到下一个图像。但从那时起,时间就变得不同步了。会发生褪色,但图像不会在正确的时间发生变化。

Fade()方法的执行时间肯定是问题的一部分。

还有你所处的环境。实时操作系统承诺在一定时间内执行任务,并且每次都按时执行。(除了一些例外。我在简化。)

同样,没有任何操作系统的嵌入式系统也可以非常可预测,因为代码行之间不会发生任何事情。如果你能准确地确定A点和B点之间发生了多少CPU周期,你就能保证一切都会按时发生。

您正在做的是在尽可能远离嵌入式系统的环境中,使用非实时操作系统来实现如此精确的计时!

即使我们忽略了这样一个现实,即你的操作系统(托管浏览器)永远无法保证事情会在你想要的时候发生(你无法在这样的浏览器中用JS解决),你仍然有一个问题-setTimeout(Fade, 100)行实际上给了你100.5ms的延迟,因为所有这些代码都必须首先执行:

tcount = count / 10;
image.style.opacity = tcount;
f1 = f1.concat((tcount * 100).toString());
image.style.filter = f1.concat(f2);
if (count > 1)
{ ...

(我希望这是有道理的。我的观点是,该函数中通往setTimeout(...)的每一行代码都需要时间来执行。)

如果你的问题仅仅是两个函数的相对定时超时(而不是5000ms永远不会精确到5000ms),那么有一个非常简单的解决方案。

从一个计时器开始执行所有操作:-)

创建一个"时钟",其间隔为所有其他时钟间隔的公共除法。在你的情况下,100毫秒就足够了,因为它可以用整数乘以5000毫秒、4000毫秒和100毫秒。

废弃所有其他代码行:

window.onload = setTimeout(Initialize, 0);
window.onload = setInterval(ImageFader, 4000);
window.onload = setInterval(ChangeImage, 5000);

相反,计算一个100毫秒时钟的执行次数。该时钟的50次执行应触发ChangeImage,40次执行应引发ImageFader,等等

这将为您提供精确的相对时间。


更新以包含示例伪代码:

var clockCount = 0;
var fading = false;
setTimeout(globalClock, 100);
function globalClock(
   clockCount++;
   if (clockCount == 40) {
      ImageFader();
   } elseif (clockCount == 50) {
      ChangeImage();
   }
   if (fading) {
      Fade();
   }
   // At end of function so we don't ever trigger multiple executions at the same time
   setTimeout(globalClock, 100);
);

删除setInterval()调用,仅使用setTimeout(),将所有计时器组织到链中:

  1. Initialize()结束时调用setTimeout(Fade, 4000)

  2. Fade()本身调用setTimeout(Fade, 100)几次,但在最后一步调用setTimeout(ChangeImage, 100)

  3. ChangeImage()结束时调用setTimeout(Fade, 4000)

以下是我使用单独的setInverval()方法处理淡入和图像更改的方法:

window.onload = setTimeout(Initialize, 0);
window.onload = setInterval(ImageFader, 8000);
function Initialize()
{
    image = document.getElementById('title-image');
    image.src = "images/image-1.jpg";
}
function ChangeImage()
{
    image = document.getElementById('title-image');
    do
    {
        num = Math.floor((Math.random() * 10) + 1);
    } while (num == lastNum);
    lastNum = num;
    temp = file.concat(num.toString());
    image.src = temp.concat(ext);
}
function ImageFader()
{
    setTimeout(Fade, 100);
}
function Fade()
{
    tcount = count / 10;
    image.style.opacity = tcount;
    f1 = f1.concat((tcount * 100).toString());
    image.style.filter = f1.concat(f2);
    if (count > 1)
    {
        count--;
        setTimeout(Fade, 100);
    }
    else
    {
        count = 10;
        ChangeImage();
        image.style.opacity = 1;
        image.style.filter = "alpha(opacity=100)";
    }
}