如何在forEach循环中每秒运行一次setTimeout?

时间:2019-04-13 18:58:29

标签: javascript loops foreach async-await settimeout

我的代码,以便在每分钟60个写限制的在线服务中创建多个展示位置:

  placementsToAdd.forEach((placement, index) => {
    setTimeout(() => {
      options.url = `https://api.company.com/placement?publisher_id=${existingPub ? existingPub : placementsJson[0].PublisherId}&site_id=${placement.siteId}`
      options.body = `{"placement":{"name":"${placement.placement}"}}`
      request(options, callback);  
    },1000 * (index + 1))
  })

这种方式可以工作,但是如果一次有2000或3000个展示位置列表,我会担心等待时间,等待时间可能会过长。

是否有更好的方法来重构此代码,以使我的请求每秒建立一次,无论如何?如果没有该“ *(索引+ 1)”,它似乎会继续尝试在60岁以后立即将所有建筑物都撞墙。

我尝试使用promises和async等待(这对我来说是新的),但是它似乎并没有改变行为。

谢谢!

根据要求,显示如何通过以下代码使用promise:

  async function createThePlacements() {
    let promise = new Promise((resolve, reject) => {
      for (let i = 0; i < placementsToAdd.length; i++) {
        setTimeout(() => {
          options.url = `https://api.company.com/placement?publisher_id=${existingPub ? existingPub : placementsJson[0].PublisherId}&site_id=${placementsToAdd[i].siteId}`
          options.body = `{"placement":{"name":"${placementsToAdd[i].placement}"}}`
          request(options, callback);  
        },1000)
      }
    });

    let result = await promise; // pause till the promise resolves 
    console.log('result - ', result);
  }

  createThePlacements();

因此,免责声明-如前所述,我从没使用过Async Await,所以请仔细阅读以了解其工作原理。这似乎是语法,但目前我的结果似乎什么都没有,但是代码也继续执行应做的工作,只是试图一次一次完成300次测试中的所有调用。

另外,值得注意的是,我在请求调用的回调内部有一个解决方法。它可以解决,因此即使我的应用程序的下一部分也一直完成到最后。这就是为什么我在这里没有拒绝或解决的原因。

2 个答案:

答案 0 :(得分:3)

  

如何在forEach循环中每秒运行一次setTimeout?

最直接的方法是:

const wait = ms => new Promise(resolve => setTimeout(resolve, ms));

for (const placement of placementsToAdd) {
  const options = {...};
  request(options, callback);  
  await wait(1000);
}

await可以在普通for循环内运行,而不是forEach内运行。

我没有碰过您的callback,但它需要处理错误。可能有更多的重构。

我认为,这里最重要的改进是我们不会提前推送请求。通过这种方式,我们可以保留控制权,并且在需要进行更改或发生任何麻烦时,我们可以摆脱循环,而不会在几分钟内向服务器发送垃圾邮件。

答案 1 :(得分:1)

最好的选择是拥有一个返回Promise的request方法。

然后您可以像这样重写代码。

function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

function requestPlacement(placement) {
  const options = {...};
  return request(options);
}

async function requestAllPlacements(placements) {
  for(let i = 0; i < placements.length; i+=60) {
    if (i > 0) {
      // wait 1 minute
      await(sleep(60000));
    }

    await Promise.all(
      placements
        .slice(i, 60)
        .map(requestPlacement);
    );
  }
}