Краткий ответ: Щелчок приведет к отложенному AJAX-запросу и, следовательно, pendingXHR.waitForAllXhrFinished()
будет немедленно разрешен, поскольку в момент выполнения функции запросы не выполняются. Вместо этого используйте page.waitForResponse('.../data/')
.
Проблема
Вы ожидаете, что произойдет следующий процесс событий:
- Клик происходит
- Запускается AJAX
pendingXHR.waitForAllXhrFinished()
выполнено
- AJAX-запрос завершается
- Таблица отображается
pendingXHR.waitForAllXhrFinished()
разрешает
page.content()
выполнено
Проблема в том, что используемая вами библиотека (PendingXHR) ожидает ожидающих в данный момент запросов и разрешается сразу после их разрешения. Это не работает в двух случаях, о которых я могу думать:
1. AJAX-запрос запускается асинхронно
В этом случае порядок событий будет таким:
- Нажатие происходит, но асинхронно запускает вызов AJAX (позже)
pendingXHR.waitForAllXhrFinished()
выполнено
pendingXHR.waitForAllXhrFinished()
разрешается немедленно (поскольку запросов нет)
page.content()
выполнено (слишком рано!)
- Запускается AJAX
- AJAX-запрос завершается
- Таблица отображается
2. Пользовательский интерфейс изменяет таблицу асинхронно
В этом случае порядок событий будет таким:
- Клик происходит
- AJAX-запрос запускается
pendingXHR.waitForAllXhrFinished()
выполнено
- AJAX-запрос завершается (но код отображает таблицу позже)
pendingXHR.waitForAllXhrFinished()
разрешает
page.content()
(слишком рано!)
- Таблица отображается
Несоответствие происходит, поскольку иногда события могут быть в правильном порядке, поскольку в этом случае миллисекунда может решить, что произойдет первым.
Fix
Не глядя на код страницы, я не могу сказать, в каком случае это точно (это может быть на самом деле и то и другое), но я бы предположил, что это первый случай, так как я могу полностью увидеть библиотеку таблиц, ожидающую любого двойной щелчок / перетаскивание / и т.д. произойдет до того, как он сделает запрос AJAX.
Первая проблема может быть исправлена с помощью page.waitForResponse
вместо pendingXHR.waitForAllXhrFinished
, поскольку это гарантирует, что запрос к data/
действительно произошел.
Исправление второго случая (при необходимости) не так тривиально, но может быть сделано путем введения фиксированного времени ожидания с помощью page.waitFor(10)
.
Исправляя оба случая, новый код выглядит так:
await Promise.all([ // wait for the response to happen and click
page.waitForResponse('.../data/'), // use the actual URL here
page.click('...'),
]);
await page.waitFor(10); // wait for any asynchronous rerenders that might happen
let html = await page.content();