首页 > 解决方案 > For循环无限运行

问题描述

所以我已经和这个 for 循环斗争了一天半了,当我让它实际打印时它会无限运行,即使 if 语句 (logCount === 10) 得到满足......不太确定该尝试什么再说了,真的觉得它比我尝试的要简单得多......

任何解决方案的尝试都值得赞赏..

var timers = [];

var log = (function(outputFunc) {

  var counter = 0;
  var callerLog = [];
  var dateTime = [];

  //assigning current Date to a variable to print for logs
  let logDate = new Date();
  return function(timer) {
    for (var logCount = 0; logCount <= 10; logCount++) {
      //printing data without using printFunc, as specified
      document.getElementById("output").innerHTML += logCount + " " + timer + " " + logDate + "<br>";

      //TODO: add after for loop is resolved.
      if (logCount >= 10) {
        clearInterval(timer1);
        clearInterval(timer2);
        clearInterval(timer3);
        document.getElementById("output").innerHTML += "<br><br/> Logging stopped.";
      }
    }
  }
})(printFunc);

function printFunc(output) {
  document.write(output + "<br>");
}

function startMeUp() {
  // add each of the timer references to the timers array
  // as part of invoking the log function following each interval
  timers.push(setInterval("log('Timer1')", 1000));
  timers.push(setInterval("log('Timer2')", 1200));
  timers.push(setInterval("log('Timer3')", 1700));
}

标签: javascriptfunctionloopsfor-loop

解决方案


我猜这就是你想要实现的目标:

function printFunc(output) {
    // Replaced with console.log for my own convenience
    console.log(output);
}

// Not really a factory, just a curry of the outputFunc
function loggerFactory(outputFunc) {
    return function startLogger(name, interval) {
        // Variables to keep track of the iterations and a reference to the interval to cancel
        let logCount = 0;
        let intervalRef;

        function tick() {
            // On each tick, check if we're done
            // If yes, clear the interval and do the last output
            // If no, do some output and increment the iterator
            // Once the next tick passes we'll check again
            // If you were using setTimeout instead you would have to requeue the tick here
            if (logCount >= 10) {
                clearInterval(intervalRef);
                outputFunc('Done ' + name);
            } else {
                outputFunc(logCount + " " + name);
                logCount += 1;
            }
        }

        // Start it of
        intervalRef = setInterval(tick, interval);
    }
}

const logger = loggerFactory(printFunc);

function startMeUp() {
    console.log('Starting');
    logger('Log1', 1000);
    logger('Log2', 1200);
    logger('Log3', 1700);
}
startMeUp();

一些注意事项:您可以将 intervalRefs 推送到一个数组中,但我发现将这些工作封装在同一个记录器中会更好,因为它应该只清理自己。

当使用间隔(或一般的异步代码)时,for 循环通常不是您想要的。for 循环本质上是同步的,所有迭代将直接在彼此之后运行,没有其他任何空间。您正在寻找的是一种同时运行多个异步“轨道”的方法。您可以使用 for 循环来启动这些“轨道”,例如:

 for () {
   logger('Log' + i, 1000 * i);
 }

但关键在于logger快速设置了interval函数,然后返回。这样,您的 for 循环可以快速“调度”任务,但记录器使用 setInterval 或 setTimeout 在内部异步运行迭代。


推荐阅读