【问题标题】:setTimeout in a for loop with varying time具有不同时间的 for 循环中的 setTimeout
【发布时间】:2020-08-10 13:55:29
【问题描述】:

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

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

因此,我想要的结果是

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

但是下面的代码会累计执行20s,即time = 5s时打印obj 3 & 5,5s后打印obj 1,10s后打印obj 2 & 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);

我的代码有什么问题?或者有什么其他方法可以达到我想要的结果?

非常感谢!

【问题讨论】:

  • 只是为了确定,您希望对象的超时在前一个对象的超时结束后开始?
  • 是的,obj 1中的时间结束后,根据它的时间执行obj 2

标签: javascript html settimeout


【解决方案1】:

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

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);

【讨论】:

  • 只回答一个解释。
【解决方案2】:

您可以使用async/awaitPromises 来实现

它的工作原理是await new Promise(...) 停止当前函数直到 Promise 完成

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);

【讨论】:

    【解决方案3】:

    你也可以像这样在递归函数中做到这一点:

    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);

    【讨论】:

    【解决方案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},
    ]
    
    var time = 0;
    
    function renderTimer(data) {
      for (let i = 0; i < data.length; i++) {
        const eachName = data[i].name;
        time += data[i].time;
        const eachTime = time * 1000;
    
        setTimeout(() => {
          console.log(eachName);
        }, eachTime);
      }
    }
    
    renderTimer(data);

    【讨论】:

      猜你喜欢
      • 2020-05-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-21
      • 2016-08-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多