如何顺序运行基于承诺的功能

时间:2019-01-10 15:38:37

标签: javascript node.js lighthouse

我正在尝试使用一组URL连续(一次一个)运行node 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 个答案:

答案 0 :(得分: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);

答案 1 :(得分:1)

您的回答是正确的,但可以改进。由于您可以访问asyncawait,因此应充分利用它来使代码更简洁:

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);

答案 2 :(得分: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);
});

答案 3 :(得分:-2)

只需将您的代码作为测试执行,我们将使用async / await和IIFE
然后,将创建函数,该函数会将我们的所有请求放入未解决的Promise数组中,因此我们可以将其与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.waterfall与某些npm包一起使用,例如this