lino-levan / astral

A high-level puppeteer/playwright-like library for Deno
https://jsr.io/@astral/astral
MIT License
248 stars 17 forks source link

How to use the `waitForFunction()` method? #112

Open ooker777 opened 20 hours ago

ooker777 commented 20 hours ago

My code:

try {
  const InputWhatsOnYourMind = await page.$("#mbasic-composer-form > table > tbody > tr > td._4g34 > div > textarea");
  InputWhatsOnYourMind.type(text) 
  await page.waitForTimeout(1000)

  const buttonSubmit = await page.$("#mbasic-composer-form > table > tbody > tr > td:nth-child(3) > div > input");
  buttonSubmit.click()
  await page.waitForNavigation()
} catch (error) {
  console.error(error);
}

The waitForTimeout is not recommended, but what else to use then? If I don't wait, then the text won't be sent in full. I suspect waitForEvent() and waitForFunction() are my choices, but I don't know how to implement them. I take a guess, suggested from this same question on Puppeteer, and modify to match the number of arguments of it:

await page.waitForFunction(() => InputWhatsOnYourMind.value === text);

But it doesn't work. Do you have any idea?

lino-levan commented 20 hours ago

waitForFunction runs the code inside the page. It doesn't have access to InputWhatsOnYourMind or text unless you pass it in as an argument.

ooker777 commented 18 hours ago

How to pass it as an argument? Either:

await page.waitForFunction((InputWhatsOnYourMind, text) => InputWhatsOnYourMind.value === text);

or

await page.waitForFunction(({InputWhatsOnYourMind, text}) => InputWhatsOnYourMind.value === text);

doesn't work.

lino-levan commented 17 hours ago

I believe you should write it like

await page.waitForFunction((InputWhatsOnYourMind, text) => InputWhatsOnYourMind.value === text, {
    args: [InputWhatsOnYourMind, text]
});

I'm not sure if passing selectors into the waitForFunction works. If not, then you should do

await page.waitForFunction((text) => document.querySelector("#mbasic-composer-form > table > tbody > tr > td:nth-child(3) > div > input").value = text, {
    args: [text]
});
ooker777 commented 3 hours ago

The first one returns:

DeadlineError: Deadline
    at https://jsr.io/@std/async/0.223.0/deadline.ts:60:32
    at eventLoopTick (ext:core/01_core.js:214:9)
    at async Page.waitForFunction (https://jsr.io/@astral/astral/0.4.8/src/page.ts:661:5)
    at async file:///D:/QC supplements/Code/Apps/Xây nhân hiệu tự động/astral.ts:37:3 {
  name: "DeadlineError"
}

The second one almost works. For this code:

const inputSelector = "#mbasic-composer-form > table > tbody > tr > td._4g34 > div > textarea"
const inputElement = await page.$(inputSelector);
inputElement.type(text) 
await page.waitForFunction((InputSelector, text) => document.querySelector(InputSelector)!.value = text, {
  args: [inputSelector, text]
});

The result repeats the first word. For example, if the text is one two three four five, then the result is one two three four fiveone.

Do you have any idea?