Javascript 表单提交后 Puppeteer 等待页面加载

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/46948489/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 03:41:00  来源:igfitidea点击:

Puppeteer wait page load after form submit

javascriptpuppeteer

提问by redochka

I submit a form using the following code and i want Puppeteer to wait page load after form submit.

我使用以下代码提交表单,我希望 Puppeteer 在表单提交后等待页面加载。

await page.click("button[type=submit]");

//how to wait until the new page loads before taking screenshot?
// i don't want this:
// await page.waitFor(1*1000);  //← unwanted workaround
await page.screenshot({path: 'example.png'});

How to wait for page load with puppeteer?

如何使用 puppeteer 等待页面加载?

回答by Md. Abu Taher

You can wait for navigation asynchronously to avoid getting nullon redirection,

您可以异步等待导航以避免null重定向,

await Promise.all([
      page.click("button[type=submit]"),
      page.waitForNavigation({ waitUntil: 'networkidle0' }),
]);

This will help you if the page.click already triggers a navigation.

如果 page.click 已触发导航,这将对您有所帮助。

回答by redochka

await page.waitForNavigation();

回答by Grant Miller

According to the Official Documentation, you should use:

根据官方文档,您应该使用:

page.waitForNavigation(options)

  • options<Object> Navigation parameters which might have the following properties:
    • timeout<number> Maximum navigation time in milliseconds, defaults to 30 seconds, pass 0to disable timeout. The default value can be changed by using the page.setDefaultNavigationTimeout(timeout)method.
    • waitUntil<string|Array<string>> When to consider navigation succeeded, defaults to load. Given an array of event strings, navigation is considered to be successful after all events have been fired. Events can be either:
      • load- consider navigation to be finished when the loadevent is fired.
      • domcontentloaded- consider navigation to be finished when the DOMContentLoadedevent is fired.
      • networkidle0- consider navigation to be finished when there are no more than 0 network connections for at least 500ms.
      • networkidle2- consider navigation to be finished when there are no more than 2 network connections for at least 500ms.
  • returns: <Promise<[?Response]>> Promise which resolves to the main resource response. In case of multiple redirects, the navigation will resolve with the response of the last redirect. In case of navigation to a different anchor or navigation due to History API usage, the navigation will resolve with null.

page.waitForNavigation(选项)

  • options<对象> 导航参数可能具有以下属性:
    • timeout< number> 最大导航时间,以毫秒为单位,默认为 30 秒,传递0给禁用超时。可以使用page.setDefaultNavigationTimeout(timeout)方法更改默认值。
    • waitUntil<字符串| Array< string>> 何时认为导航成功,默认为load。给定一组事件字符串,在触发所有事件后,导航被认为是成功的。事件可以是:
      • load- 考虑在load触发事件时完成导航。
      • domcontentloaded- 考虑在DOMContentLoaded触发事件时完成导航。
      • networkidle0- 当至少500ms 的网络连接数不超过 0 时,考虑完成导航。
      • networkidle2- 考虑在至少500ms内没有超过 2 个网络连接时完成导航。
  • 返回:< Promise<[?Response]>> Promise 解析为主要资源响应。在多次重定向的情况下,导航将使用上次重定向的响应进行解析。如果由于 History API 的使用而导航到不同的锚点或导航,导航将使用null.

Readability:

可读性:

You can use page.waitForNavigation()to wait for a page to navigate:

您可以使用page.waitForNavigation()等待页面导航:

await page.waitForNavigation();

Performance:

表现:

But since page.waitForNavigation()is a shortcut for page.mainFrame().waitForNavigation(), we can use the following for a minor performance enhancement:

但由于page.waitForNavigation()是 的快捷方式page.mainFrame().waitForNavigation(),我们可以使用以下内容进行较小的性能增强:

await page._frameManager._mainFrame.waitForNavigation();

回答by Austin

I know it is bit late to answer this. It may be helpful for those who are getting below exception while doing waitForNavigation.

我知道现在回答这个有点晚了。对于那些在执行waitForNavigation 时遇到异常情况的人可能会有所帮助。

(node:14531) UnhandledPromiseRejectionWarning: TimeoutError: Navigation Timeout Exceeded: 30000ms exceeded at Promise.then (/home/user/nodejs/node_modules/puppeteer/lib/LifecycleWatcher.js:142:21) at -- ASYNC -- at Frame. (/home/user/nodejs/node_modules/puppeteer/lib/helper.js:111:15) at Page.waitForNavigation (/home/user/nodejs/node_modules/puppeteer/lib/Page.js:649:49) at Page. (/home/user/nodejs/node_modules/puppeteer/lib/helper.js:112:23) at /home/user/nodejs/user/puppeteer/example7.js:14:12 at

(node:14531) UnhandledPromiseRejectionWarning: TimeoutError: Navigation Timeout Exceeded: Promise.then (/home/user/nodejs/node_modules/puppeteer/lib/LifecycleWatcher.js:142:21) at -- ASYNC -- at Frame 超过 30000ms。(/home/user/nodejs/node_modules/puppeteer/lib/helper.js:111:15) 在 Page.waitForNavigation (/home/user/nodejs/node_modules/puppeteer/lib/Page.js:649:49) 在 Page . (/home/user/nodejs/node_modules/puppeteer/lib/helper.js:112:23) 在 /home/user/nodejs/user/puppeteer/example7.js:14:12 在

The correct code that worked for me is as below.

对我有用的正确代码如下。

await page.click('button[id=start]', {waitUntil: 'domcontentloaded'});

Similarly if you are going to a new page, code should be like

同样,如果你要进入一个新页面,代码应该像

await page.goto('here goes url', {waitUntil: 'domcontentloaded'});

回答by Nathan Goings

Sometimes even using await page.waitForNavigation()will still result in a Error: Execution context was destroyed, most likely because of a navigation.

有时即使使用await page.waitForNavigation()仍会导致Error: Execution context was destroyed, most likely because of a navigation.

In my case, it was because the page was redirecting multiple times. The APIsays the default waitUntiloption is Load—this required me to wait for navigation each redirect (3 times). Using only a single instance of page.waitForNavigationwith the waitUntiloption networkidle2worked well in my case:

就我而言,这是因为页面多次重定向。该API表示默认waitUntil选项Load-这种要求我等待导航每个重定向(3次)。在我的情况下,仅使用page.waitForNavigation带有waitUntil选项的单个实例networkidle2效果很好:

await button.click();

await page.waitForNavigation({waitUntil: 'networkidle2'});

Finally, the API suggests using a Promise.Allto prevent a race condition. I haven't needed this but provide it for completeness:

最后,API 建议使用 aPromise.All来防止竞争条件。 我不需要这个,但提供它是为了完整性

await Promise.all([button.click(), page.waitForNavigation({waitUntil:'networkidle2'})])

If all else fails, you can use page.waitForSelectoras recommended on a Puppeteer github issue—or in my case, page.waitForXPath()

如果所有其他方法都失败了,您可以page.waitForSelector按照Puppeteer github 问题上的建议使用——或者在我的情况下,page.waitForXPath()

回答by Andrea Bisello

i suggest to wrap page.to in a wrapper and wait for everything loaded

我建议将 page.to 包装在一个包装器中并等待加载所有内容

this is my wrapper

这是我的包装纸

loadUrl: async function (page, url) {
    try {
        await page.goto(url, {
            timeout: 20000,
            waitUntil: ['load', 'domcontentloaded', 'networkidle0', 'networkidle2']
        })
    } catch (error) {
        throw new Error("url " + url + " url not loaded -> " + error)
    }
}

now you can use this with

现在你可以使用它

await loadUrl(page, "https://www.google.com")

回答by Denish S.

await Promise.all([
      page.click(selectors.submit),
      page.waitForNavigation({ waitUntil: 'networkidle0' }),
]);

This would be the first priority to use as it waits for all network to complete and assumes it is done when you don't have more than 0 network call for 500ms.

这将是使用的第一优先级,因为它等待所有网络完成并假设在 500 毫秒内没有超过 0 个网络调用时完成。

you can also use

你也可以使用

await page.waitForNavigation({ waitUntil: 'Load' }}

or else, you can use

否则,你可以使用

await page.waitForResponse(response => response.ok())

this function can also be used in various places as it only allows to proceed further when all the calls are a success that is when all the response status is ok i.e (200-299)

这个函数也可以用在不同的地方,因为它只允许在所有调用都成功时,即所有响应状态都正常时,即 (200-299) 进一步进行

回答by Tomá? Hübelbauer

I ran into a scenario, where there was the classic POST-303-GET and an input[type=submit]was involved. It seems that in this case, the clickof the button won't resolve until after the associated form's submission and redirection, so the solution was to remove the waitForNavigation, because it was executed after the redirection and thus was timing out.

我遇到了一个场景,其中有经典的 POST-303-GET 并且input[type=submit]参与其中。在这种情况下,click按钮的似乎在关联表单提交和重定向之后才会解析,因此解决方案是删除waitForNavigation,因为它是在重定向之后执行的,因此超时。