Tengo el código a continuación, y estoy tratando de trabajar con if
/ else if
.
El problema es que tengo problemas para detectar qué función apareció en la página y continuar con los pasos correctos. En realidad, detecta la función dentro del primero if
aparece, obviamente, pero cuando aparece la función del segundo if
aparece, no la detecta, o espera para siempre solo la primera función, luego falla por el tiempo de espera de la función.
¿Qué debo hacer con mi script para detectar cuál apareció y luego continuar con los pasos correctos para cada función detectada? Solo uno de ellos aparece por intento.
if (await page.waitForFunction('document.querySelector("body").innerText.includes("Configurando sua conta...")')){ console.log('Function 1 appeared, doing steps for function 1 (below)'); await page.waitForNavigation(); await page.waitForTimeout(100000); await page.goto('website-secret'); } else if (await page.ForFunction('document.querySelector("body").innerText.includes("Você não está qualificado")')){ console.log('Function 2 appeared, doing steps for function 2 (below)') await page.waitForTimeout(1200000); await page.goto('website-secret'); }
Hay algunas maneras.
La forma más sencilla es usar un try
para detectar el error que aparece cuando no se encuentra un elemento y luego pasar al siguiente. Esto tiene sentido cuando desea priorizar uno sobre el otro:
try { await page.waitForFunction("condition 1"); // condition 1 logic } catch (err) { await page.waitForFunction("condition 2"); // condition 2 logic }
El uso de condiciones para el flujo de control es feo, y es posible que deba anidar más si le preocupa el lanzamiento de la lógica de cualquiera de las condiciones (casi todas las funciones de Puppeteer pueden lanzar).
En los comentarios se mencionó un enfoque probablemente mejor: Promise.race
, que acepta una serie de promesas y regresa cuando al menos una se resuelve. Aquí hay un ejemplo:
const assert = require("node:assert/strict"); const puppeteer = require("puppeteer"); // ^14.3.0 const html = ` <body> <p></p> <script> setTimeout(() => { document.querySelector("p").textContent = ~~(Math.random() * 2); }, 2000); </script> </body> `; let browser; (async () => { browser = await puppeteer.launch({headless: true}); const [page] = await browser.pages(); const query = "document.querySelector('p')?.textContent === "; const conditions = [ page.waitForFunction(query + "'0'"), page.waitForFunction(query + "'1'"), ].map(async (promise, index) => { const result = await promise; return {result, index}; }); const fastestCondition = Promise.race(conditions); await page.setContent(html); const fastestResult = await fastestCondition; const pText = await page.$eval("p", el => el.textContent); assert(fastestResult.index === +pText); console.log(pText); // => sometimes 0, sometimes 1 })() .catch(err => console.error(err)) .finally(() => browser?.close()) ;
Este código se lanzará si cualquiera de las promesas se rechaza.
El mapeo de índice se usa para determinar qué promesa tuvo éxito en la línea principal, pero también puede encadenar todo el código dependiente después de cada waitFor...
si nunca necesita volver a unirse a la línea principal.
También puede usar allSettled
para averiguar qué promesas se rechazaron y cuáles no.