提问者:小点点

在可变时间的for循环中设置Timeout


我有一个不同对象的数组,每个对象包含不同值的时间属性。

我想为这个数组循环,里面有一个setTimeout函数,时间将是每个对象的时间属性。

所以,我想要的结果是

  1. 10s后,打印第一个对象的名称
  2. 20s后,打印第二对象名称
  3. 。。。
  4. 。。。
  5. 5s后,打印上一个对象的名称。

然而,下面的代码将在总共20秒的累积中执行,这就是打印obj3&; 5当时间=5s时,5s后打印obj1,10s后打印obj2& 4。

const data = [
{name: "Warm up", timeFormat: "00:10", time: 10},
{name: "High interval", timeFormat: "00:20", time: 20},
{name: "Low Interval", timeFormat: "00:05", time: 5},
{name: "High interval", timeFormat: "00:20", time: 20},
{name: "Low Interval", timeFormat: "00:05", time: 5},
]

function renderTimer(data) {
  for (let i = 0; i < data.length; i++) {
    const eachName = data[i].name;
    const eachTime = data[i].time;

    setTimeout(() => {
      console.log(eachName);
    }, eachTime * 1000);
  }
}

renderTimer(data);

我的代码有什么问题? 或者其他任何方式来达到我想要的结果?

非常感谢!


共3个答案

匿名用户

所发生的情况是,程序在for循环中快速运行,并几乎立即设置相对于t=0s的超时。 如果要使用setTimeout(),则必须自己累积计时:

null

const data = [
{name: "Warm up", timeFormat: "00:10", time: 10},
{name: "High interval", timeFormat: "00:20", time: 20},
{name: "Low Interval", timeFormat: "00:05", time: 5},
{name: "High interval", timeFormat: "00:20", time: 20},
{name: "Low Interval", timeFormat: "00:05", time: 5},
]

function renderTimer(data) {
  var timing = 0;
  for (let i = 0; i < data.length; i++) {
    const eachName = data[i].name;
    timing += data[i].time;

    setTimeout(() => {
      console.log(eachName);
    }, timing * 1000);
  }
}

renderTimer(data);

匿名用户

您可以使用async/awaitpromises来执行此操作

它使用Await new Promise(。。。)停止当前函数直到Promise实现

null

const data = [
  {name: "Warm up", timeFormat: "00:10", time: 10},
  {name: "High interval", timeFormat: "00:20", time: 20},
  {name: "Low Interval", timeFormat: "00:05", time: 5},
  {name: "High interval", timeFormat: "00:20", time: 20},
  {name: "Low Interval", timeFormat: "00:05", time: 5},
]

async function renderTimer(data) {
  for (let i = 0; i < data.length; i++) {
    const eachName = data[i].name;
    const eachTime = data[i].time;

    await new Promise(res => {
      setTimeout(() => {
        console.log(eachName);
        // resolve the promise once the log is done
        res()
      }, eachTime * 100)}
    )
    // can't arrive here until the setTimeout is finalized
  }
}

renderTimer(data);

匿名用户

您也可以在递归函数中这样做:

null

const data = [
{name: "Warm up", timeFormat: "00:10", time: 10},
{name: "High interval", timeFormat: "00:20", time: 20},
{name: "Low Interval", timeFormat: "00:05", time: 5},
{name: "High interval", timeFormat: "00:20", time: 20},
{name: "Low Interval", timeFormat: "00:05", time: 5},
]

const renderTimer = (data, i = 0) => {
  setTimeout(() => {
    console.log(data[i].name);
    
    // Call for next data
    if(i < data.length - 1)
      renderTimer(data, i + 1);
  }, data[i].time * 1000);
}

renderTimer(data);