Синхронное связывание переменного числа обещаний, которые совместно используют ресурс в Javascript - PullRequest
0 голосов
/ 27 апреля 2019

Я пытаюсь использовать Chrome lighthouse , чтобы проверить количество URL-адресов из списка. Я могу сделать это с одним 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, выполнить функцию lighthouse для каждого URL, а затем, наконец, вызвать 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 Launcher в качестве начального значения.

  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 Ответ

1 голос
/ 28 апреля 2019

с асинхронным ожиданием:

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

Classic:

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);
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...