【问题标题】:Javascript loops/functions/setTimeoutJavascript 循环/函数/setTimeout
【发布时间】:2017-06-25 03:56:46
【问题描述】:

我想每 5 秒循环一次数组(“站点”)。 5(“cycle_timeout”)秒后,我想调用另一个函数,该函数以 1 秒的间隔循环遍历 0 到 120 的值。当 looper 函数在循环之外调用时,它可以正常工作,但我希望从循环内部调用它。发生这种情况时,不会保留循环“延迟”,并且循环会非常快速地从 0 加速到 120。如何让 Looper 以 1 秒的间隔继续?感谢您的帮助。

var i = 0;
var l = 120;
looper(); // looper runs correctly when invoked from here.
function looper() {
    var Delay = 1;
    console.log("i is ", i);
    i = i + 1;
    if (i == l) {
        i = 0;
    }
    setTimeout(looper, Delay * 1000);
}
var sites = ["a", "b"];
var lengthsites = sites.length;
var ii = 0;
cycle();
function cycle() {
    console.log("ii is ", ii);
    console.log("site is ", sites[ii]);
    var cycle_timeout = 5;
    setTimeout(cycle, cycle_timeout * 1000);
    //looper(); // looper accelerates when invoked from here.
    ii = ii + 1;
    if (ii == lengthsites) {
        ii = 0;
    }
}

【问题讨论】:

  • 如果你写的代码看起来像这样,你总会遇到问题——缩进让事情更容易阅读(当然,你可能是个天才,我猜你可能不需要格式正确的代码)
  • 在编辑代码示例的格式时,我不禁注意到有很多分号丢失。这可能会产生各种意想不到的结果,应该先修复,测试,如果问题仍然存在,我们可以继续。请参阅this question - 尽管有人只是在我打字时覆盖了我的编辑并“修复”了它们,所以我们可能永远不知道这是否是一个问题。
  • oops - 我在格式化代码中添加了缺少的;,因为我是个白痴:p
  • 请使用 setInterval() 而不是 setTimeout 以便以重复方式调用函数。然后你就不需要在它调用的函数中调用 setTimeout 了。

标签: javascript function loops for-loop settimeout


【解决方案1】:

因为这个原因,它从内部加速:

function looper () {
  // stuff
  callLooperIn1Second();
}

function cycle () {
  // stuff
  looper();
  callCycleIn5Seconds();
}

Looper 每秒都会调用自己。 Cycle 会每 5 秒调用一次 looper,它会每秒调用一次自己。 所以每 5 秒,cycle 再次调用looper,它会增加它计划运行的时间。您增加了 looper 那一秒被调用的次数。

当您第一次调用 cycle 时,looper 将每秒运行一次。
5 秒后,它将每秒运行 2 次。
10 秒后,它将每秒运行 3 次。

cycle // call looper, which schedules every 1s
looper
looper
looper
looper
looper
cycle // call looper, which schedules every 1s
looper looper
looper looper
looper looper
looper looper
looper looper
cycle // call looper, which schedules every 1s
looper looper looper
looper looper looper
looper looper looper
looper looper looper
looper looper looper

将其切换为使用 setInterval 是行不通的,因为那样你只会每 5 秒在 looper 上导致 cyclesetInterval,这比完成相同问题的代码略少。

我建议打破你的流程并安排代码远离你真正打算做的事情。

let currentSecond = 0;
const totalSeconds = 120;

const sites = ["a", "b", "c"];
const totalSites = sites.length;
let siteIndex = 0;

function looper (i) {
  currentSecond = (i + 1) % totalSeconds;
}
function cycle (i) {
  const site = sites[i];
  siteIndex = (i + 1) % totalSites;
}

function triggerLoop () {
  const loopDelayMS = 1000;
  looper(currentSecond);
  setTimeout(triggerLoop, loopDelayMS);
}

function triggerCycle () {
  const cycleDelayMS = 5000;
  cycle(siteIndex);
  setTimeout(triggerCycle, cycleDelayMS);
}

function run () {
  triggerLoop();
  triggerCycle();
}

当然,您可以走得更远。
你可以在不同的时间间隔运行这些东西,而不是递归超时。这样就好了。

您可以使流程更加相互依赖,这也很好...除了您需要添加很多更多的计时器管理代码,以计算出多长时间looper 是,在它的计数中,这对于 cycle 每次被解雇意味着什么。

这两个计数器看起来并没有以任何可能的方式相互连接。您希望一个在 2 分钟内每秒计数一次,并且您希望另一个每 5 秒计数一次,只要数组中有元素,并且您希望它们都重置并在达到极限时继续运行.据我所知,计时器彼此之间没有任何关系。只是他们被捆绑在导致他们行为不端的代码中。

【讨论】:

    猜你喜欢
    • 2016-07-04
    • 1970-01-01
    • 2014-05-16
    • 1970-01-01
    • 1970-01-01
    • 2013-01-25
    • 1970-01-01
    • 2013-09-15
    • 2021-03-06
    相关资源
    最近更新 更多