如何根据索引/迭代次数动态更改For循环中的间隔时间?


12

由于我无法发表评论,因此我不得不撰写这篇文章。我得到下面的代码,它延迟/恰好延迟1秒或1000毫秒-

let n = 5;
for (let i=1; i<n; i++)
{
  setTimeout( function timer()
  {
      console.log("hello world");
  }, i*1000 );
}

但是,我如何将其延迟* 1000秒而不是固定的1000毫秒,所以等待取决于迭代次数?

例如,如果n = 5,那么我希望在第一次迭代中将循环延迟设为1秒。在第二次迭代中2秒,依此类推...最终延迟将为5秒。


2
所以你想做9个计时器吗?如果是这样,那么您的代码将满足您的要求。它不会精确地等待3秒。实际上,计时器永远不会是精确的。
Scott Marcus

1
您的问题没有道理
DanStarns

2
只需在Codepen中尝试一下代码即可:codepen.io/Connum/pen/BaaBMwW您将获得9条消息,间隔3000毫秒 -如果这不是您想要的(但从您的问题听起来确实如此),请指定您的预期结果是。
康斯坦丁·格罗斯

1
您似乎首先不了解setTimeout的工作原理-它不是 “延迟”。现在,您得到您的警报3秒的间隔,因为你已经有成倍的增加了3000 i-如果你不这样做,那么你会得到所有这些警报在同一时间。
04FS

3
编辑问题以使最后一句变为粗体并不能真正帮助您解决问题。现在,多个注释器告诉您,您的代码已经完成了您要的操作(或者,如果不是您想要的结果,则您实际上并不清楚要执行的操作)。
康斯坦丁·格罗斯

Answers:


6

这是一个将立即显示的函数,然后是1秒钟,然后是2秒钟,之后是3秒钟,依此类推。无需特殊数学,无需承诺

const n = 5;
let cnt=0;

function show() {
  console.log("call "+cnt,"delay: ",cnt,"sec");
  cnt++;
  if (cnt > n) return; // we are done
  setTimeout(show, cnt*1000 ); // cnt seconds later
}
show()


1
非常遗憾,我错过了您的答案,有这么多评论,误解,答案……无论如何,我选择您的答案是因为您是第一个解决我先生的问题的人。
麦克,

@迈克·哈尔 其他解决方案本身也很有用,因此感谢您的接受
-mplungjan

Pavan的ES6语法相同。很难阅读,但实际上是一样的。他所做的编辑是在我写我的文章的同时进行的:)
mplungjan

8

虽然可以用promises,反应流和其他很酷的工具解决这个任务(嘿,还没有人建议使用worker!),但是也可以用一点算术来解决。

因此,您需要按以下顺序超时:1s,前一个+ 2s,前一个+ 3s,依此类推。该序列为:1、3、6、10、15 ...,其公式为a[n] = n * (n + 1) / 2。知道...

let n = 6;
console.log(new Date().getSeconds());

for (let i = 1; i < n; i++) {
  setTimeout(function timer() {
    console.log(new Date().getSeconds());
  }, 1000 * i * (i + 1) / 2);
}


数学家还活着!:)
Bilal Siddiqui

5

您可以尝试使用async / await(承诺)序列化代码:

const waitSeconds = seconds => new Promise(resolve => setTimeout(resolve, seconds))

async function main () {
 let oldDate = new Date()
 let newDate
 
 /* 
  * If you put 'await' inside the loop you can synchronize the async code, and simulate
  * a sleep function
  */
 for (let i=1; i<5; i++) {
    await waitSeconds(i*1000)
    newDate = new Date()   
    console.log(`Loop for i=${i}, elapsed=${moment(newDate).diff(oldDate, 'seconds')} seconds`)
    oldDate = newDate
 }
 
 console.log('End')
}

main()
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script>


5

花了我一些时间来解释您的问题xD,但这是您想要的吗?

这将每次以i * 1000的延迟触发console.log。因此,第一次将是1秒长(1 * 1000),然后将是2秒,依此类推。

let i = 0;
loop = () => {
  setTimeout(() => {
    console.log(new Date()); // for clarity
    i++;
    if (i < 10) {
      loop();
    }
  }, i * 1000)
};
loop();


例如,如果n = 5,那么我希望在第一次迭代中将循环延迟设为1秒。在第二次迭代中2秒,依此类推...最终延迟将为5秒。
迈克,

是的,第一次迭代将延迟1秒,第二次迭代将延迟2秒,依此类推,尝试一下
Pavan Skipo,

您的描述与代码不匹配。但这确实可以胜任
mplungjan '19

3

循环不等待超时功能完成。因此,当循环运行时,它会为每个索引安排警报。

您可以使用将根据您的索引运行但同时计划的功能。您可以感觉到3秒的差别。

function test(i){
    setTimeout( function timer(){
        console.log("hello world" + i);
    }, i*3000);
}
for (let i=1; i<4; i++) {
   test(i);
}

3

使用递归调用而不是for循环

let i=1;
function a(i) {
  if (i > 5)
    return
  else
    b("message", i)
}

function b(s, f) {
  setTimeout(function timer() {
    console.log(s + " " + f + " seconds");
  }, f * 1000);
  a(++i);
}
a(i);


例如,如果n = 5,那么我希望在第一次迭代中将循环延迟设为1秒。在第二次迭代中2秒,依此类推...最终延迟将为5秒。
迈克,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.