7

Trying puppeteer for the first time and it is amazing. I need to wait for a page to fetch and render new data after a button click. This does not cause a navigation (the url is the same) so the following code does not work (it gives timeout exception):

await Promise.all([
    myButton.click()
    page.waitForNavigation()
])

What's the correct way to wait for the page to fetch/render async data on click?

revy
  • 3,945
  • 7
  • 40
  • 85

3 Answers3

8

Assuming the DOM changes in some way, you can wait for a specific element or selector.

Maybe an image appears.

await myButton.click();
await page.waitForSelector('img.success');

Maybe some element with an ID attribute is inserted into the DOM.

await myButton.click();
await page.waitForSelector('#newElementThatAppeared');

If you're unfamiliar with DOM selectors, you can read up here and here. They're powerful and easy to use.

Update - Custom wait predicate.

If we always know the length...

await myButton.click();
await page.waitFor(() => document.querySelectorAll('ul.specialList li').length > 5);

If we know the length will increase

const listSize = await page.evaluate(() => document.querySelectorAll('ul.specialList li').length);
await myButton.click();
await page.waitFor(() => document.querySelectorAll('ul.specialList li').length > listSize);
Tom Faltesek
  • 2,768
  • 1
  • 19
  • 30
  • Hi! The data fetched will update an already non empty list of
  • , so I am afraid I can’t rely on the presence of specific selector...maybe wait for the list to change size? But how?
  • – revy Aug 23 '19 at 15:49
  • Hmm. Could you update the question with a relevant snippet of the **before click** state of the DOM and the **after click** state? I may be able to help a bit more with those details. – Tom Faltesek Aug 23 '19 at 15:52