typescript 如何检查 Puppeteer 页面是否处于导航状态?

fjnneemd  于 2023-01-18  发布在  TypeScript
关注(0)|答案(2)|浏览(146)

我在Puppeteer之上写了一些 Package 器,我有一个通用的“click”函数和一个“getHtml”函数:

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;
    }
}

如您所见,click()函数只接收querySelector,然后单击找到的任何元素。
问题是,如果此元素单击导致导航,后续操作可能会遇到此错误:
执行上下文已损坏,很可能是由于导航
例如,如果客户端代码执行类似以下操作:

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

是否有任何方法,检查是否有一个挂起的导航,以便我可以有条件地等待它,在各种功能?

在click函数中,我不能只默认waitForNavigation,因为这将导致代码挂起,以防单击导致没有导航。

ugmeyewa

ugmeyewa1#

也许像这样的变通方案会有所帮助?

const [_, navigation] = await Promise.allSettled([
  elem.click(),
  page.waitForNavigation(),
]);

if (navigation.status === 'fulfilled') /* There was navigation. */;
else /* There was timeout, no navigation. */;
zf9nrax1

zf9nrax12#

两年后...

我登陆这里是因为我在调用page.goto()和随后的page.content()之后得到了Execution context was destroyed [...]

**医生

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

如果由于设置location.hrefHistory.pushState()而没有后续重定向,则page.waitForSelector('html')将立即解决,并且一旦导航成功就等待(一个重定向)。

-为什么会发生这种情况?

在我的例子中,这是由于页面加载后设置的location.href。在这种情况下,内容是在页面被导航到一个新地址时请求的。

-为什么不是page.waitForNavigation()

page.waitForNavication()总是阻塞直到导航成功。就像OP一样,我不能假设导航总是发生,我也不能事先知道它何时发生。我想避免不必要的阻塞,所以这个方法不是一个可行的选择。

-缺点

如果服务器响应的不是有效的HTML负载,page.waitForSelector('html')将阻塞并最终超时,并抛出错误。

相关问题