Javascript循环:精确时间后运行函数

时间:2015-11-01 05:12:59

标签: javascript

我已经搜索了这个问题的解决方案(我能理解)并且还没找到。

在这里小提琴 https://jsfiddle.net/the_o/a7dwp41s/

目标: 在一段时间后(例如1秒)更改文本。

问题: 时机不准确。它在小提琴中并不明显,但在我的页面上,文字有时会变得太快。有时循环也会停止。我知道setTimeout在读取其他Stack Overflow答案时并不准确,但是在准确的设定时间段之后没有遇到运行函数的好方法。我很感激一些帮助。

HTML:

 <span class="text-center"><span class="top-line">A heading here</span>
<br><span class="bottom-line">There once was a...<br>
 <span id="changeTextMobile"></span></span>
</span>

Javascript:

var text = ["carrot", "potato", "tomato", "lettuce", "radish", "cabbage", "melon", "cucumber"];
var elem = document.getElementById("changeTextMobile");

var counter = 0;

function rotate_text() {
    elem.innerHTML = text[counter];
    if (counter < 8) {
        counter++window.setTimeout(rotate_text, 1200);
    }
    if (counter == 8) {
        counter = 0;
    }
}

rotate_text();

这里又是小提琴:https://jsfiddle.net/the_o/a7dwp41s/

3 个答案:

答案 0 :(得分:1)

这里的经典方法是设置一个细粒度的计时器(使用setTimeout或更可能requestAnimationFrame,然后在其中检查当前时间并计算与前一时间的差异,并执行如果所需的时间已经过去,你的行动.RAF会向你的回调发送一个高分辨率计时器,如果你对亚毫秒精度感兴趣,可以使用它。

var text = ["carrot", "potato", ...];
var elem = document.getElementById("changeTextMobile");
var counter = 0;
var DELAY = 1000;
var old_timestamp = 0;

function rotate_text(timestamp) {
  if (timestamp > old_timestamp + DELAY) {  // HAVE WE WAITED LONG ENOUGH?
    update_vegetable();                     // CHANGE VEGETABLE NAME.
    old_timestamp = timestamp;              // REMEMBER WHEN WE DID THAT.
  }
  requestAnimationFrame(rotate_text);       // RINSE AND REPEAT
}

rotate_text(0);

其中update_vegetable看起来像

function update_vegetable() {
  elem.textContent = text[counter++ % 8];
}

这应该会给你非常准确的结果。但请注意,当标签位于后台时,某些浏览器可能会降低requestAnimationFrame的速度。另请注意,requestAnimationFrame可能需要在某些浏览器中使用供应商前缀。

如果您因某些原因不想使用requestAnimationFrame,您应该可以使用setTimeout(tick, 16)替换对counter的调用,并获得类似的结果。

分析当前代码

在当前代码中,当setTimeout达到8并将其重置为0时,您不再次调用if (counter == 8) { counter = 0; //YOU ARE NOT RESETTING THE TIMEOUT. } 来继续序列。这似乎不对。

counter % 8

在任何情况下,您最好使用counter作为另一个答案建议,如上所示。

此外,下面的行似乎已损坏,并且缺少分号。这是你的实际代码吗?它会做的是将counter++window.setTimeout(rotate_text, 1200); 添加到setTimeout返回的计时器ID,这完全没有意义。

counter++;
window.setTimeout(rotate_text, 1200);

应该是

hash_key

答案 1 :(得分:0)

实现目标的另一种方法是使用setInterval()方法而不是setTimeout()方法。

该方法的文档可在W3Schools.com

上找到

除非我误解你的意图,否则你不仅要改变你的文本一次,而是要反复改变。在这种情况下,setInterval()是选择,因为setTimeout()仅用于运行一次函数。这可能是您的一致性问题的根源。

如果您希望停止计时器的重复功能,请在触发器中使用clearInterval()

答案 2 :(得分:0)

对于此类情况,您应该使用setInterval。我已更新JSFiddle

的setTimeout

setTimeout用于在执行函数之前必须添加延迟的情况。

的setInterval

setInterval用于在一定时间延迟后必须运行某些功能的情况。

另外,只需注释,setTimeout(function(){},0)并不意味着它会立即执行。当您使用这些函数时,会注册一个事件以在特定时间点执行,因此setTimeout(function(){},0)将在下一个时间点触发而不是立即触发。

&#13;
&#13;
var text = ["carrot", "potato", "tomato", "lettuce", "radish", "cabbage", "melon", "cucumber"];
var counter = 0;

function initInterval() {
  interval = setInterval(function() {
    counter++;
    $("#changeTextMobile").text(text[counter % 8]);
  }, 1200);
}

$(document).ready(function() {
  initInterval();
});
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<span class="text-center"><span class="top-line">A heading here</span>
<br><span class="bottom-line">There once was a...<br>
 <span id="changeTextMobile"></span></span>
</span>
&#13;
&#13;
&#13;

希望它有所帮助。