13

I use Puppeteer library to open an URL and process all requests' responses. Sometimes inside the event listener page.on('response') I need to throw an error like in the example below. But I'm unable to catch these exceptions in any way, I always got the unhandled promise rejection error. How can I handle these exceptions? I don't want to use process.on('unhandledRejection') because it doesn't solve my problem at all.

const puppeteer = require('puppeteer');

(async () => {
    try {
        const browser = await puppeteer.launch();
        const page = await browser.newPage();

        page.on('response', (request) => {
            throw 'response error';
        });

        await page.goto('http://google.com/');

        browser.close();
    } catch (e) {}
})();
pronngo
  • 820
  • 11
  • 26
  • 1
    [Here](https://stackoverflow.com/questions/41431605/handle-error-from-settimeout) you may have the same issue – Orelsanpls Sep 19 '17 at 13:45
  • To handle error from event listeners use promises , much better explanation in link in above comment – Solaris Mar 06 '21 at 12:24

3 Answers3

5

Although the function of your page.on handler is located inside a try..catch block, the function is executed asynchronously and therefore any error thrown inside this function is not caught by the outer try..catch block.

You have to create another try..catch block inside your function.

Example

const puppeteer = require('puppeteer');

function handleError(err) {
    // ...
}

(async () => {
    try {
        const browser = await puppeteer.launch();
        const page = await browser.newPage();

        page.on('response', (request) => {
            try { // inner try catch block to catch errors inside this function
                // ...
                throw 'response error';
            } catch (err) {
                // Handle the error here, or pass it to another function:
                handleError(err);
            }
        });

        await page.goto('http://google.com/');

        browser.close();
    } catch (e) {}
})();
Thomas Dondorf
  • 23,416
  • 6
  • 84
  • 105
1

I would never put responses in event handlers as you will most definately run into the problem of express trying to send multiple responses to a user resulting in an error (except if you create a an event handler that manages if it has been called before and then supress sending a response but that is also not pretty). I would use a Promise.race condition.

This would wait for the first one of your promises to either reject or resolve. Even though your page.on cannot resolve that's ok because page.goto should do that or also reject.

So this would look somewhat like this

try {
  await Promise.race([
    new Promise((res,rej) => page.on('error', error => rej(error))),
    page.goto('http://google.com/')
  ]);
  // Do stuff if got succeeds
  browser.close();

catch (err) {
  // do stuff with your error
  browser.close();
}
relief.melone
  • 3,042
  • 1
  • 28
  • 57
-3

All you need to do to avoid that error is to catch the result of the async function, which is a Promise, and handle it somehow, even if just piping it through console.error.

const puppeteer = require('puppeteer');

(async () => {
    try {
        const browser = await puppeteer.launch();
        const page = await browser.newPage();

        page.on('response', (request) => {
            throw 'response error';
        });

        await page.goto('http://google.com/');

        browser.close();
    } catch (e) {}
})().catch(console.error);