Ожидание загрузки 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()