Ожидание загрузки Puppeteer после отправки формы

Я отправляю форму, используя следующий код, и я хочу, чтобы 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'});

Как подождать загрузки страницы с помощью кукловода?

Ответ 1

Вы можете ожидать асинхронной навигации, чтобы избежать перенаправления null,

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

Это поможет вам, если page.click уже запускает навигацию.

Ответ 2

await page.waitForNavigation();

Ответ 3

Согласно официальной документации, вы должны использовать:

page.waitForNavigation (варианты)

  • options < Object > Параметры навигации, которые могут иметь следующие свойства:
    • timeout < число > Максимальное время навигации в миллисекундах, по умолчанию 30 секунд, пройти 0 чтобы отключить тайм-аут. Значение по умолчанию можно изменить с помощью метода page.setDefaultNavigationTimeout(timeout).
    • waitUntil < строка | Array < string >> Когда считается, что навигация выполнена успешно, по умолчанию load. При наличии массива строк событий навигация считается успешной после запуска всех событий. События могут быть:
      • load - считать навигацию завершенной, когда происходит событие load.
      • domcontentloaded - считать навигацию завершенной при DOMContentLoaded события DOMContentLoaded.
      • networkidle0 - считать навигацию завершенной, если в течение не менее 500 мс не более 0 сетевых подключений.
      • networkidle2 - считается, что навигация завершена, если в течение не менее 500 мс существует не более 2 сетевых подключений.
  • возвращает: < Promise <[? Response] >> Promise, которое разрешается в ответ основного ресурса. В случае нескольких перенаправлений навигация разрешается с ответом последнего перенаправления. В случае перехода к другой привязке или навигации из-за использования History API, навигация разрешится с null.

Читаемость:

Вы можете использовать page.waitForNavigation() для ожидания перехода по странице:

await page.waitForNavigation();

Спектакль:

Но поскольку page.waitForNavigation() является ярлыком для page.mainFrame().waitForNavigation(), мы можем использовать следующее для незначительного повышения производительности:

await page._frameManager._mainFrame.waitForNavigation();

Ответ 4

Я знаю, что уже поздно ответить на это. Это может быть полезно для тех, кто получает исключение во время выполнения waitForNavigation.

(узел: 14531) UnhandledPromiseRejectionWarning: TimeoutError: Превышено время ожидания навигации: превышено 30000 мс в Promise.then(/home/user/nodejs/node_modules/puppeteer/lib/LifecycleWatcher.js:142:21) в - ASYNC - в кадре. (/home/user/nodejs/node_modules/puppeteer/lib/helper.js:111:15) в Page.waitForNavigation(/home/user/nodejs/node_modules/puppeteer/lib/Page.js:649:49) на странице, (/home/user/nodejs/node_modules/puppeteer/lib/helper.js:112:23) в /home/user/nodejs/user/puppeteer/example7.js:14:12 в

Правильный код, который работал для меня, как показано ниже.

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

Точно так же, если вы собираетесь на новую страницу, код должен выглядеть так:

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

Ответ 5

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

Это будет первый приоритет, который нужно использовать, так как он ожидает завершения всей сети и предполагает, что это делается, когда у вас не более 0 сетевых вызовов в течение 500 мс.

Вы также можете использовать

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

или вы можете использовать

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

эта функция также может использоваться в разных местах, так как она позволяет продолжить, только если все вызовы успешны, то есть когда все статусы ответа в порядке, т.е. (200-299)

Ответ 6

Иногда даже использование await page.waitForNavigation() все равно приводит к Error: Execution context was destroyed, most likely because of a navigation.

В моем случае это было потому, что страница была перенаправлена несколько раз. API говорит, что по умолчанию опция waitUntil - Load - это требовало от меня ждать перехода каждого перенаправления (3 раза). Использование только одного экземпляра page.waitForNavigation с опцией waitUntil networkidle2 хорошо работало в моем случае:

await button.click();

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

Наконец, API предлагает использовать Promise.All для предотвращения состояния гонки. Я не нуждался в этом, но предоставил это для полноты:

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

Если ничего не помогает, вы можете использовать page.waitForSelector, как рекомендовано для проблемы с gupub Puppeteer - или в моем случае, page.waitForXPath()