在 Javascript 中同步链接可变数量的共享资源的承诺
Chaining a variable number of promises synchronously that share a resource in Javascript
我正在尝试使用 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
创建浏览器 window,在每个 url 上执行 lighthouse
函数,然后最后在 window 上调用 chrome.kill()
, 在 return 结果之前。
最初,我尝试使用 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
都使用共享资源,他们必须等待上一次调用 return 才能继续,而 Promise.all 尝试并行进行所有灯塔调用,然后解决。这不适用于单个共享浏览器资源。
然后我尝试使用减速器进行试验,将 chrome 启动器承诺作为初始值。
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)
但这在调用 lighthouse 函数时也不起作用,但我认为这是同步调用承诺链的正确方法。
有没有人对我出错的地方有任何建议,或者我还可以尝试什么?
使用异步等待:
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);
});
我正在尝试使用 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
创建浏览器 window,在每个 url 上执行 lighthouse
函数,然后最后在 window 上调用 chrome.kill()
, 在 return 结果之前。
最初,我尝试使用 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
都使用共享资源,他们必须等待上一次调用 return 才能继续,而 Promise.all 尝试并行进行所有灯塔调用,然后解决。这不适用于单个共享浏览器资源。
然后我尝试使用减速器进行试验,将 chrome 启动器承诺作为初始值。
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)
但这在调用 lighthouse 函数时也不起作用,但我认为这是同步调用承诺链的正确方法。
有没有人对我出错的地方有任何建议,或者我还可以尝试什么?
使用异步等待:
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);
});