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

问题描述 投票:2回答:2

我的代码是为了在每分钟写入约束为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 await(这对我来说是新的)但它似乎并没有改变行为。

谢谢!

根据要求,显示我如何尝试使用此代码的promises:

  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测试中同时进行所有调用。

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

javascript loops foreach async-await settimeout
2个回答
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
投票

最好的选择是使用返回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);
    );
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.