UnhandledPromiseRejectionWarning:错误:页面崩溃!在使用p时

时间:2019-09-16 12:13:46

标签: javascript node.js mocha puppeteer

所以我使用了while循环,所以我的测试将以恒定循环运行,直到后端崩溃为止。 我已经实现了try and catch(error),所以任何前端崩溃都会自动刷新并保持运行

while(true){
try{
    await page.waitFor(selector)
    await page.click(selector)    
}
catch(error){
    console.log("FE crashed with\n\n" + error + "\n\nRefreshing page and continuing profile switching")
    await page.reload(page);
    continue;
}}

因此,实际上,任何超时错误都会自动刷新页面并继续循环。 但是我收到了另一个崩溃错误

(node:6535) UnhandledPromiseRejectionWarning: Error: Page crashed!
at Page._onTargetCrashed (/home/raymond/node_modules/puppeteer/lib/Page.js:170:24)
at CDPSession.Page.client.on.event (/home/raymond/node_modules/puppeteer/lib/Page.js:125:56)
at CDPSession.emit (events.js:182:13)
at CDPSession._onMessage (/home/raymond/node_modules/puppeteer/lib/Connection.js:200:12)
at Connection._onMessage (/home/raymond/node_modules/puppeteer/lib/Connection.js:112:17)
at _tickCallback (internal/process/next_tick.js:43:7)
at listOnTimeout (timers.js:294:7)
at processTimers (timers.js:268:5)
(node:6535) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 2)

如何处理此错误?,如果我手动刷新页面,一切正常。 谢谢

2 个答案:

答案 0 :(得分:3)

您假设该错误是由于页面导航失败而发生的。可能是这种情况,但也可能是一个不同的错误,例如Protocol error。在这种情况下,您不能仅重用page对象,而必须首先重新启动浏览器。

前一段时间,我crawled roughly 400k pages for testing purposes。总共,我经历了34次这些操纵up的崩溃,其中某些意外错误使整个浏览器崩溃。为了使您的代码免受此类崩溃的破坏,您需要一种可靠的方法来重新启动浏览器。

代码示例

let browser = await puppeteer.launch(/* .. */);
let page = await browser.newPage();

while(true) {
    try {
        // your code that might crash
    } catch (err) {
        try {
            await page.reload(); // soft fix
        } catch (recoveringErr) {
            // unable to reload the page, hard fix
            try {
                await browser.close();
            } catch (err) { // browser close was not necessary
                // you might want to log this error
            }
            browser = await puppeteer.launch(/* .. */);
            page = await browser.newPage();
        }
    }
}

尽管此代码看起来很可怕,带有三个嵌套的try..catch块,但是它在保持代码运行方面做得很好。

首先,执行原始代码。如果发生最初的问题,则尝试进行page.reload调用以解决问题。在这种情况下,循环将继续运行。如果不起作用,将重新启动浏览器。

要重新启动浏览器,建议您先尝试关闭旧的浏览器。尽管这可能会失败,但是它会清除所有内存并正确配置浏览器对象。根据您的用例,您可能想要记录错误或将其忽略。处置旧的浏览器对象后,可以重新启动浏览器,循环可能会继续。

替代

作为替代方案,您可以使用我的库puppeteer-cluster,该库内置了错误处理功能。如果页面不再可用,该库会自动重新启动浏览器。此外,该库可以并行运行多个页面(在尝试对我假设的服务器进行压力测试时)。

答案 1 :(得分:0)

根据官方文档,页面崩溃时会发出“错误”事件,可用于根据应用程序做某些事情。

page.on('error', err => { /*custom logic to handle the crash*/ });

对于上述特定用例,您可以执行以下操作:

let browser = await puppeteer.launch();
let page = await getNewPage(browser);

while(true){
        try{
            if (page.isClosed()) {
              page = await getNewPage(browser);
            }
            await page.waitFor(selector)
            await page.click(selector)    
        }
        catch(error){
            console.log("FE error with\n\n" + error + "\n\nRefreshing page and continuing profile switching")
            await page.reload();
            continue;
        }}


async function getNewPage(browser) {
    let page = await browser.newPage();
    page.on('error', err => {
        if (!page.isClosed()) {
            //Close page if not closed already
            page.close();
        }
    }
    return page;
}

参考:page.on('error')