【问题标题】:How to manually pause and execute for batch of records using map and promises in javascript?如何在javascript中使用map和promises手动暂停和执行批量记录?
【发布时间】:2019-10-28 08:32:36
【问题描述】:
function sleep(ms) {
  var start = new Date().getTime(),
    expire = start + ms;
  while (new Date().getTime() < expire) {}
  return;
}

async function executeWithDelay(offers) {
  return Promise.all(
    offers.map((offer, i) =>
      getDetailedInfo(offer).then(data => {
        offer = data;
        if (i % 5 === 0) {
          console.log('executed but it delays now for 3 seconds');
          sleep(3000);
        }
      })
    )
  ).then(function(data) {
    return offers;
  });
}

尝试使用可能的最佳解决方案来实现网络抓取。我将 Cheerio 和 puppeteer 结合在一起,我有一些不错的代码要调试。如果报价数据较少,即 5-10 条记录,则上述代码可以正常工作。如果超过,浏览器会崩溃,尽管我在无头版本中运行。

这基本上是由于我正在使用的包中的内部错误无法处理负载。我的实验是对每批记录进行一点延迟,并完成完整的记录执行。

但是对于下面的代码,它表现为非阻塞代码,并且第一次延迟和休息不断执行。

我应该使用 for 循环而不是 map 还是有其他方法来处理这种情况?

【问题讨论】:

    标签: javascript google-chrome puppeteer cheerio


    【解决方案1】:

    你永远不想在这样的忙等待循环中“睡觉”。这意味着在主线程上不能做任何其他事情。

    一旦 Promise 所代表的操作已经开始,除非它们提供一些自定义的暂停它们的方法,否则你不能暂停它们。请记住,承诺实际上并没有任何事情。它们提供了一种观察正在做的事情的标准方法。

    该代码的另一个问题是您返回的是offers,而不是调用getExtendedInfo 的结果。

    如果问题是过于频繁地调用getExtendedInfo,您可以插入延迟(使用setTimeout,而不是忙循环)。例如,这几乎立即执行对getExtendedInfo 的第一个请求,一秒后执行下一个请求,两秒后执行下一个请求,依此类推:

    function sleep(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }
    
    function executeWithDelay(offers) {
      return Promise.all(
        offers.map((offer, i) =>
          sleep(i * 1000).then(getDetailedInfo)
        )
      });
    }
    

    显然,您可以根据需要调整该延迟。

    (注意executeWithDelay 没有声明为async;不需要,因为它必须使用Promise.all。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-25
      • 2011-08-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-08
      相关资源
      最近更新 更多