2

我正在尝试使用一组 URL 串行(一次一个)运行节点 js Lighthouse 函数。我的问题是,每当我遍历数组时,Lighthouse 会同时运行所有 URL,我想如果你有一个非常大的 URL 数组,这是有问题的。

编码:

for(let url of urls) {        
  function launchChromeAndRunLighthouse(url, opts, config = null) {
    return chromeLauncher.launch({chromeFlags: opts.chromeFlags}).then(chrome => {
      opts.port = chrome.port;
      return lighthouse(url, opts, config).then(results => {
        return chrome.kill().then(() => results.lhr)
      });
    });
  }
}

launchChromeAndRunLighthouse('https://example.com', opts).then(results => {
  // Use results!
});

请帮忙!谢谢你的时间!

4

4 回答 4

4

您的答案是正确的,但可以改进。由于您可以访问asyncand await,因此您应该充分利用它来使您的代码更干净:

async function launchChromeAndRunLighthouse (url, opts, config = null) {
  const chrome = await chromeLauncher.launch({chromeFlags: opts.chromeFlags});
  opts.port = chrome.port;
  const { lhr } = await lighthouse(url, opts, config);
  await chrome.kill();
  return lhr;
}

async function launchAudit (urls) {
  for (const url of urls) {
     const results = await launchChromeAndRunLighthouse(url, opts);
     // Use results!
  };
}

launchAudit(urls);
于 2019-01-10T16:27:37.343 回答
1

我相信我想通了。我所做的如下。如果您认为这是错误的,请继续发送反馈。

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

async function launchAudit(urls) {
  for (let url of urls) {
     await launchChromeAndRunLighthouse(url, opts).then(results => {
       // Use results!
     });
  };
};

launchAudit(urls);
于 2019-01-10T16:19:01.230 回答
0

Patric Roberts 答案的变体(应该是公认的答案)。

我想知道是否有必要在每次迭代时都杀死 chrome。

const lighthouse = require('lighthouse');
const chromeLauncher = require('chrome-launcher');

function launchChromeAndRunLighthouse(sites, opts, config = null) {
    return chromeLauncher.launch({chromeFlags: opts.chromeFlags}).then(chrome => {
    opts.port = chrome.port;
    const siteResults = [];
    return new Promise((resolve, reject) => {

        // batch async functions.
        // C/O https://stackoverflow.com/questions/43082934/how-to-execute-promises-sequentially-passing-the-parameters-from-an-array
        const runBatch = async (iterable, action) => {
            for (const x of iterable) {
                await action(x)
            }
        }

        // func to run lighthouse
        const doLightHouse = (site) => new Promise((resolve, reject) => {
            lighthouse(site, opts, config).then(results => {
                siteResults.push(results.lhr);
                resolve();
            });

        });

        // go go go
        runBatch(sites, doLightHouse).then(d => {
            chrome.kill().then((result) => {
                resolve(siteResults)
            })
        });
    });

});
}

const opts = {
    chromeFlags: ['--show-paint-rects'],
    onlyCategories: ['performance']
};

const sites = ['https://www.example.com', 'https://www.test.com']

launchChromeAndRunLighthouse(sites, opts).then(results => {
   // Use results!
    console.log(results);
});
于 2020-04-24T16:37:52.983 回答
-2

只是为了执行你的代码作为测试,我们将使用 async/await 和IIFE
然后,将创建一个函数,它将我们所有的请求放到未解决的承诺数组中,所以我们可以使用它 你需要用这样的方式重写代码:Promise.all()

(async() => {
  const promisesToExecute = [];

  const launchChromeAndRunLighthouse = async (url, opts, config = null) => {
     const chrome = await return chromeLauncher.launch({chromeFlags: opts.chromeFlags});
     opts.port = chrome.port;

     promisesToExecute.push(lighthouse(url, opts, config));
  }

  const results = await Promise.all(promisesToExecute);

  for(const result of results) {
    const resolvedResult = await result.kill();
    // here you can access your  results.lhr
    console.log(resolvedResult.lhr);
  }
})()

请注意,此代码未经测试,因此结果可能存在问题kill()。但是,主要目标是回答您的问题并解释如何执行承诺。
另外,如果你不想同时执行所有的 Promise,你可以使用 Promise.waterfall 和一些 npm 包,像这样

于 2019-01-10T16:10:55.300 回答