javascript – Pass a function inside page.waitForFunction() with puppeteer

javascript – Pass a function inside page.waitForFunction() with puppeteer

page.waitForFunction() accepts a callback and right now youre passing in a boolean. To solve this you can do the following :

  await page.waitForFunction((pastAvgGain, currentAvgGain) => {
  if (pastAvgGain!== currentAvgGain) {
      return true
  } else {
      return false
  }
} , {} , pastAvgGain, currentAvgGain )

https://github.com/puppeteer/puppeteer/blob/main/docs/api.md#pagewaitforfunctionpagefunction-options-args see documentation for more info

the third parameter is the arguments you want to pass to the callback

after your comment :

  await page.waitForFunction(() => {
      return hasDataBeenRefreshed(pastAvgGain, currentAvgGain); 
  } )

There are multiple issues and misunderstandings with the code here.

The first problem is that youre calling the function you want to pass as a callback immediately. This results in the return value of the callback (a boolean comparison) being passed into page.waitForFunction rather than the callback itself. You cant call a boolean like a function, so an error is thrown.

Secondly, youll need to pass the data in as parameters to the callback using the variable arguments to page.waitForFunction. The second argument is a configuration object, so the call will look like page.waitForFunction(predicate, configObj, ...args) where ...args are the variable arguments to predicate.

Thirdly, youre getting text content before and after a click, but polling for further changes on these two variables wont work because the value of let currentAvgGain = C.AVG_GAIN.textContent will never change. Your predicate will either terminate instantly or spin based on whatever the initial values were. If click is asynchronous, then C.AVG_GAIN.textContent is probably stale and youll want to re-select the latest text content from the node in the waitForFunction predicate.

Furthermore, its not clear what C.AVG_GAIN.textContent even is. Neither DOM nodes or Puppeteer elementHandles look like this, so Ill assume this also needs to be rewritten.

It appears youre trying to check whether a DOM element, elementHandle or selector has changed its text. This should be a pretty generic function you can use:

const puppeteer = require(puppeteer);

const waitForTextChange = async (
  page,
  elOrSel,
  opts={polling: mutation, timeout: 30000}
) => {
  const el = typeof elOrSel === string 
    ? await page.$(elOrSel) : elOrSel
  ;
  const originalText = await el.evaluate(el => el.textContent);
  return page.waitForFunction(
    (el, originalText) => el.textContent !== originalText,
    opts, el, originalText, 
  );
};

let browser;
(async () => {
  const html = `
    <h2>foo</h2>
    <script>
      setTimeout(() => document.querySelector(h2).innerText = bar, 4000);
    </script>
  `;
  browser = await puppeteer.launch();
  const [page] = await browser.pages();
  await page.setContent(html);
  await waitForTextChange(page, h2);
  console.log(await page.$eval(h2, el => el.innerText)); // => bar
})()
  .catch(err => console.error(err))
  .finally(() => browser?.close())
;

javascript – Pass a function inside page.waitForFunction() with puppeteer

Leave a Reply

Your email address will not be published.