0

我正在针对大约 50 个站点列表运行灯塔 cli 。我只是在一个.forEach循环中运行它,如果我理解的话,它是阻塞的,也就是同步的。但是,我最终一次性启动了 50 个 Chrome Canary 实例。在我对这些事情的有限理解中,我认为线程是同步启动的,但随后node可以将线程传递给内核并愉快地启动下一个。同样,这只是我对正在发生的事情的随意理解。

我正在使用我从某处抄袭的这个功能:

function launchChromeAndLighthouse(url, opts, config = null) {
  return chromeLauncher.launch({chromeFlags: opts.chromeFlags}).then(chrome => {
    opts.port = chrome.port;
    return lighthouse(url, opts, config).then(results =>
      chrome.kill().then(() => results));
  });
}

nextTick我在循环中尝试过:

asyncFuncs().then( async (sites) => {
  sites.forEach( (site) => {
    process.nextTick(launchChromeAndRunLighthouse(site.url, opts))
  })
})

但这仍然会产生一堆 Chrome 实例。如何在一个灯塔完成时暂停执行?

4

1 回答 1

1

由于launchChromeAndRunLighthouse()返回一个承诺以标记何时完成,如果您只想一次连续运行它们,您可以切换到for循环并使用await

asyncFuncs().then( async (sites) => {
  for (let site of sites) {
    await launchChromeAndRunLighthouse(site.url, opts);
  }
});

如果您尝试收集所有结果:

asyncFuncs().then( async (sites) => {
    let results = [];
    for (let site of sites) {
      let r = await launchChromeAndRunLighthouse(site.url, opts);
      results.push(r);
    }
    return results;
}).then(results => {
    // all results here
}).catch(err => {
    // process error here
});

如果您想一次运行 N 个 chrome 实例,使其最初启动 N 个实例,然后每次一个完成时,您启动下一个正在等待的实例,这对于跟踪正在运行的实例数量更加复杂。有一个辅助函数调用,pMap()或者mapConcurrent()可以在这些答案中为您执行此操作:

向一个 API 发出多个请求,每分钟只能处理 20 个请求

Promise.all 消耗了我所有的内存


Bluebird Promise 库在其Promise.map()功能中也有并发控制。

于 2018-01-27T03:21:37.777 回答