【问题标题】:For loop won't iterateFor循环不会迭代
【发布时间】:2021-08-18 02:52:32
【问题描述】:

我有一个可以完美运行的函数,直到我将它放在一个 for 循环中——此时我在 Safari 中得到一个参考错误(找不到 i)。在 Chrome 和 Firefox 中,它只运行第一次迭代(即 i = 0)。怎么回事?

编辑:这里 for 循环的要点是在其中的函数(包括超时)完成时进行迭代。如果有人对如何做到这一点有其他建议,那就太好了。

没有for循环的函数:

let realScores = [40,7, 3, 2]
let scores = [0,0,0,0]
  
  let i = 0
  let counter = 0
  function timer() {
    setTimeout(() => {
      scores[i]++
      console.log(i, scores[i])
      if (scores[i] < realScores[i]) {
        timer()
      }
    }, 10)
  }
  timer()

还有 for 循环:

let realScores = [40,7, 3, 2]
let scores = [0,0,0,0]

for (let i = 0; i < scores.length; i++) {
  let counter = 0
  function timer() {
    setTimeout(() => {
      scores[i]++
      console.log(i, scores[i])
      if (scores[i] < realScores[i]) {
        timer()
      }
    }, 10)
  }
  timer()
}

【问题讨论】:

  • 您在循环体内定义了一个新的let i = 0,它隐藏了循环定义中定义的i。即代码第 4 行中的 i 和代码第 9 行中的 i 是两个不同的变量。所以当然,在循环体内对i 的任何引用都是0
  • Ups,这只是调整我的代码以在此处上传时出现的错误。现已更正。该问题在 Safari 中仍然存在。在其他浏览器中,它虽然不如预期的那样工作。我正在尝试让 for 循环在超时功能完成后进行迭代。

标签: javascript for-loop settimeout


【解决方案1】:

For 循环是同步的,这意味着它们将在 setTimeout 完成之前执行 - 您不能暂停 for 循环的执行以等待 setTimeout 回调的解决。

幸运的是,您可以使用 Promises 和 async/await 来阻止 for 循环的执行以等待 setTimeout 解决:

let realScores = [40,7, 3, 2]
let scores = [0,0,0,0]

function timer(i) {
  return new Promise((resolve, reject) => {
    const t = () => {
      setTimeout(() => {
        scores[i]++;
        console.log(i, scores[i])
        if (scores[i] < realScores[i]) {
          t();
        } else {
          resolve();
        }
      }, 10);
    }
    t();
  }); 
}
(async() => {
  for (let i = 0; i < scores.length; i++) {
  let counter = 0;
  await timer(i);
}
console.log(scores);
})();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-05
    • 2021-04-27
    • 1970-01-01
    • 2019-10-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多