Skip to content Skip to sidebar Skip to footer

Pass A Function Inside Page.waitforfunction() With Puppeteer

Here's my code : function hasDataBeenRefreshed(pastAvgGain, currentAvgGain) { if (pastAvgGain!== currentAvgGain) { return true } else { return false } } async fu

Solution 1:

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

await page.waitForFunction((pastAvgGain, currentAvgGain) => {
  if (pastAvgGain!== currentAvgGain) {
      returntrue
  } else {
      returnfalse
  }
} , {} , 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(() => {
      returnhasDataBeenRefreshed(pastAvgGain, currentAvgGain); 
  } )

Solution 2:

There are multiple issues and misunderstandings with the code here.

The first problem is that you're 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 can't call a boolean like a function, so an error is thrown.

Secondly, you'll 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, you're getting text content before and after a click, but polling for further changes on these two variables won't 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 you'll want to re-select the latest text content from the node in the waitForFunction predicate.

Furthermore, it's not clear what C.AVG_GAIN.textContent even is. Neither DOM nodes or Puppeteer elementHandles look like this, so I'll assume this also needs to be rewritten.

It appears you're 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);
  awaitwaitForTextChange(page, "h2");
  console.log(await page.$eval("h2", el => el.innerText)); // => bar
})()
  .catch(err =>console.error(err))
  .finally(() => browser?.close())
;

Post a Comment for "Pass A Function Inside Page.waitforfunction() With Puppeteer"