Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to check if a Puppeteer Page is currently in navigation state?

I'm writing some wrapper on top of Puppeteer. I have a general "click" function, and a "getHtml" one:

class Page {
    
        ....

    async click(selector: string) {

        await this.context.evaluate((querySelector, text) => {

            const elem = document.querySelector(querySelector) as HTMLInputElement;

            if (elem) {

                elem.click();
            }

        }, selector);
    }

    async getHtml() {//

        const html = await this.context.evaluate(() => {
            return document.querySelector('html')?.innerHTML;
        })

        return html;
    }
}

As you can see, click() function just receives a querySelector , and then clicks whatever element is found.

Problem is, that if this element click causes navigation, the subsequent operations might encounter this error:

Execution context was destroyed, most likely because of a navigation

For example, if the client code does something like this:

const page = new Page(...)
...

await page.click('someSelector')//If this selector matches a link, navigation is triggered.

await page.getHtml()//Then there is an Error

Is there any way, to check if there is a pending navigation, so that i could conditionally wait for it, within various functions?

I cannot just waitForNavigation by default, within the click function, because this will cause the code to hang, in case there was no navigation caused by the click.

like image 240
i.brod Avatar asked Nov 28 '25 11:11

i.brod


1 Answers

2 Years Later...

I landed here because I was getting the Execution context was destroyed [...] after calling page.goto() and a subsequent page.content().

tl;dr

// dirty hack to avoid blocking of 'page.waitForNavigation()'
await page.waitForSelector('html')

page.waitForSelector('html') would immediately resolve if there is no subsequent redirects due to setting location.href or History.pushState() and wait (for one redirect) as soon as the navigation succeeds.

- Why this happens?

In my case it was due to a location.href that was set after page was loaded. In this case content was request as the page was being navigated to a new address.

- Why not page.waitForNavigation()

page.waitForNavication() always blocks until a navigation succeeds. Just like OP, I could not assume that a navigation always happens and I also could not know when it happens beforehand. I wanted to avoid unnecessary blocking so this method was not a viable option.

- Shortcomings

If server responds with anything other than a valid HTML payload, page.waitForSelector('html') would block and finally timeout, throwing an error.

like image 175
Yan Foto Avatar answered Nov 30 '25 00:11

Yan Foto