同步链接可变数量的Promise,这些Promise共享Javascript资源

时间:2019-04-27 20:10:55

标签: javascript promise es6-promise lighthouse

我正在尝试使用Chrome lighthouse来检查列表中的许多URL。我可以使用他们的示例代码来成功处理一个网址。

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 => {
      // use results.lhr for the JS-consumeable output
      // https://github.com/GoogleChrome/lighthouse/blob/master/types/lhr.d.ts
      // use results.report for the HTML/JSON/CSV output as a string
      // use results.artifacts for the trace/screenshots/other specific case you need (rarer)
      return chrome.kill().then(() => results.lhr)
    });
  });
}

但是,我想检查多个URL。这将需要使用chromeLauncher.launch创建浏览器窗口,在每个URL上执行lighthouse函数,然后最终在窗口上调用chrome.kill(),然后返回结果。

最初,我尝试使用Promise.all

解决此问题
  return chromeLauncher.launch({chromeFlags: opts.chromeFlags}).then(chrome => {
    opts.port = chrome.port;

    const checks = urls.map((url) => {
      console.log('checking', url)
      return lighthouse(url, opts, config)
    })

    return Promise.all(checks).then((results) => {
      return chrome.kill().then(() => results)
    })
  });

但是由于每次对lighthouse的调用都使用共享资源,因此它们必须等待上一个调用返回才能继续,而Promise.all尝试并行进行所有灯塔调用,然后进行解析。这不适用于单个共享浏览器资源。

然后,我尝试使用chrome启动器promise作为初始值的reducer进行实验。

  const checks = urls.reduce((previous, url) => {
    return previous.then((previousValue) => {
      return lighthouse(url, opts, config)
    })
  }, chromeLauncher.launch({chromeFlags: opts.chromeFlags}))

  checks
    .then((results) => {
      console.log('something')
      return chrome.kill()
    })
    .then((results) => results.lhr)

但这在调用灯塔函数时也不起作用,但是我认为这是同步调用承诺链的正确方法。

有人对我要去哪里有什么建议吗,或者我还能尝试什么?

1 个答案:

答案 0 :(得分:1)

异步等待:

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

async function launchChromeAndRunLighthouse(urls, opts, config = null) {
    const chrome = await chromeLauncher.launch({chromeFlags: opts.chromeFlags})
    opts.port = chrome.port;
    const results = [];
    for (const url of urls) {
         results.push(await lighthouse(url, opts, config));
    }
    await chrome.kill();
    return results;
}

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

// Usage:
const urls = ['http://www.google.de', 'http://www.heise.de'];
launchChromeAndRunLighthouse(urls, opts).then(results => {
    console.log(results);
});

经典:

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

function launchChromeAndRunLighthouse(urls, opts, config = null) {
    return chromeLauncher.launch({chromeFlags: opts.chromeFlags}).then(chrome => {
        opts.port = chrome.port;

        const results = [];
        return urls.reduce((p, url) => {
            return p.then(() => {
                return lighthouse(url, opts, config).then((data) => {
                    results.push(data);
                    return results;
                });
            });
        }, Promise.resolve())
            .then(() => chrome.kill())
            .then(() => results)
    });
}

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

// Usage:
const urls = ['http://www.google.de', 'http://www.heise.de'];
launchChromeAndRunLighthouse(urls, opts).then(results => {
    console.log(results);
})

或使用像Bluebird这样的库:

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

function launchChromeAndRunLighthouse(urls, opts, config = null) {
    return chromeLauncher.launch({chromeFlags: opts.chromeFlags}).then(chrome => {
        opts.port = chrome.port;

        return Promise.mapSeries(urls, url => lighthouse(url, opts, config))
            .then((results) => chrome.kill().then(() => results))
    });
}

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

// Usage:
const urls = ['http://www.google.de', 'http://www.heise.de'];
launchChromeAndRunLighthouse(urls, opts).then(results => {
    console.log(results);
});