将同步代码插入异步代码

时间:2018-01-27 03:12:42

标签: javascript node.js multithreading asynchronous lighthouse

我正在针对~50个网站站点列表运行lighthouse 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实例。如何在一个灯塔完成时暂停执行?

1 个答案:

答案 0 :(得分: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()可以在这些答案中为您执行此操作:

Make several requests to an API that can only handle 20 request a minute

Promise.all consumes all my RAM

Bluebird Promise library在其Promise.map() function中也有并发控制。