在 NodeJS v10.x.x 环境中,当尝试从某些 HTML 代码创建 PDF 页面时,每次尝试对其执行某些操作(setCacheEnabled、setRequestInterception 等...)时,我都会遇到关闭页面问题。 :
async (page, data) => {
try {
const {options, urlOrHtml} = data;
const finalOptions = { ...config.puppeteerOptions, ...options };
// Set caching flag (if provided)
const cache = finalOptions.cache;
if (cache != undefined) {
delete finalOptions.cache;
await page.setCacheEnabled(cache); //THIS LINE IS CAUSING THE PAGE TO BE CLOSED
}
// Setup timeout option (if provided)
let requestOptions = {};
const timeout = finalOptions.timeout;
if (timeout != undefined) {
delete finalOptions.timeout;
requestOptions.timeout = timeout;
}
requestOptions.waitUntil = 'networkidle0';
if (urlOrHtml.match(/^http/i)) {
await page.setRequestInterception(true); //THIS LINE IS CAUSING ERROR DUE TO THE PAGE BEING ALREADY CLOSED
page.once('request', request => {
if(finalOptions.method === "POST" && finalOptions.payload !== undefined) {
request.continue({method: 'POST', postData: JSON.stringify(finalOptions.payload)});
}
});
// Request is for a URL, so request it
await page.goto(urlOrHtml, requestOptions);
}
return await page.pdf(finalOptions);
} catch (err) {
logger.info(err);
}
};
我在某处读到,此问题可能是由于缺少某些等待而引起的,但这看起来不像我的情况。
我没有直接使用 puppeteer,而是使用这个库在其上创建一个集群并处理进程:
最佳答案
您已经给出了解决方案,但由于这是图书馆的常见问题(我是作者 🙂),我想提供更多见解。
任务功能如何工作
当作业排队并准备好执行时,puppeteer-cluster将创建一个页面并使用创建的 page
对象和排队数据调用任务函数(指定给 cluster.task
)。然后,集群等待 Promise 完成(履行或拒绝),然后关闭页面并执行队列中的下一个作业。
由于异步函数隐式创建 Promise,这意味着一旦赋予 cluster.task 函数的异步函数完成,页面就会关闭。确定该页面将来是否可能被使用并没有什么神奇的事情发生。
等待异步事件
下面是一个存在常见错误的代码示例。用户可能希望在关闭页面之前等待外部事件,如下面的(不起作用)示例所示:
无法工作(!)的代码示例:
await cluster.task(async ({ page, data }) => {
await page.goto('...');
setTimeout(() => { // user is waiting for an asynchronous event
await page.evaluate(/* ... */); // Will throw an error as the page is already closed
}, 1000);
});
在此代码中,在执行异步函数之前页面已关闭。正确的方法是返回一个 Promise。
工作代码示例:
await cluster.task(async ({ page, data }) => {
await page.goto('...');
// will wait until the Promise resolves
await new Promise(resolve => {
setTimeout(() => { // user is waiting for an asynchronous event
try {
await page.evalute(/* ... */);
resolve();
} catch (err) {
// handle error
}
}, 1000);
});
});
在此代码示例中,任务函数会一直等待,直到内部 Promise 得到解析,直到它解析该函数。这将使页面保持打开状态,直到异步函数调用 resolve
。此外,代码使用 try..catch
block ,因为库无法捕获异步代码块内引发的事件。
关于node.js - 当我与 Puppeteer(集群)交互时关闭页面,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56018295/