Latenode

Conditions d’attente personnalisées avec waitForFunction dans Puppeteer

Améliorez vos scripts Puppeteer grâce à des conditions d’attente personnalisées avec waitForFunction, afin de garantir des interactions fiables avec du contenu web dynamique.

9 min de lecture
Illustration de conditions d’attente personnalisées dans Puppeteer

Vous voulez que vos scripts Puppeteer gèrent mieux les sites web dynamiques ? Voici l’essentiel : waitForFunction vous permet de définir des règles d’attente personnalisées pour garantir le bon fonctionnement de votre automatisation avec des contenus qui évoluent.

Pourquoi utiliser waitForFunction ?

  • Contrôler le timing : attendez que des conditions précises soient remplies (par exemple, le chargement d’éléments ou la modification de texte).
  • Gérer le contenu dynamique : idéal pour les sites web modernes et dynamiques.
  • Éviter les erreurs : évitez les délais inutiles et les interactions prématurées.

Comment cela fonctionne :

  • Écrivez des conditions JavaScript qui renvoient true lorsqu’elles sont satisfaites.
  • Utilisez des options telles que la fréquence d’interrogation (raf, mutation ou millisecondes) et les délais d’expiration pour améliorer les performances.
  • Combinez des vérifications du DOM avec des réponses d’API pour des cas d’usage avancés.

Exemple :

await page.waitForFunction(
  () => document.querySelector('.status').textContent === 'Ready'
);

Fonctionnalités clés :

  • Surveillez la visibilité des éléments, leur contenu textuel ou leurs propriétés personnalisées.
  • Combinez plusieurs conditions pour des workflows complexes.
  • Gérez les délais d’expiration et les erreurs avec élégance.

Conseil : utilisez waitForFunction pour remplacer les appels sleep obsolètes et améliorer l’efficacité.

Aperçu rapide :

FonctionnalitéRôle
Modes d’interrogationVérifie les conditions via « raf », « mutation » ou des intervalles personnalisés
Conditions personnaliséesAttend des états DOM spécifiques ou des réponses d’API
Gestion des délais d’expirationDéfinit des délais propres à l’opération ou globaux

Cette méthode garantit que vos scripts sont fiables, efficaces et prêts à relever tous les défis liés au contenu dynamique.

Comment attendre / suspendre l’exécution pendant N secondes dans puppeteer ?

Principes de base de waitForFunction

La méthode waitForFunction de Puppeteer vous permet de définir des conditions personnalisées que vos scripts doivent attendre avant de poursuivre leur exécution. Voici comment l’utiliser efficacement.

Comment écrire des fonctions d’attente simples

Voici une méthode simple pour créer une fonction d’attente :

// Wait until the input element has a specific value
await page.waitForFunction(
  'document.getElementById("loginUsername").value === "hello"'
);

// Using an arrow function for a condition
await page.waitForFunction(
  () => document.querySelector('.status').textContent === 'Ready'
);

L’élément essentiel est que votre fonction doit renvoyer une valeur véridique avant que le script puisse continuer [1].

Voyons maintenant comment la configurer pour optimiser ses performances.

Configuration des paramètres de fonction

Vous pouvez affiner waitForFunction en lui transmettant un objet d’options. Les paramètres clés incluent :

ParamètreDescriptionValeurs courantes
pollingFréquence de vérification de la condition« raf », « mutation » ou millisecondes
timeoutDurée maximale d’attentePar défaut : 30 000 ms (30 secondes)

Modes d’interrogation [4] :

  1. RequestAnimationFrame (« raf »)
    Idéal pour surveiller les changements de style, car il vérifie les conditions à chaque image d’animation.

  2. Mutation Observer (« mutation »)
    Utile pour suivre les modifications de la structure du DOM. Il déclenche des vérifications à chaque mise à jour du DOM.

  3. Intervalle personnalisé (millisecondes)
    Par exemple, cette configuration vérifie la condition chaque seconde :

    await page.waitForFunction(
      () => document.readyState === 'complete',
      { polling: 1000, timeout: 5000 }
    );
    

Choisissez le mode d’interrogation selon vos besoins :

  • Utilisez 'raf' pour les animations ou les mises à jour de style.
  • Préférez 'mutation' pour les modifications liées au DOM.
  • Définissez un intervalle personnalisé (en millisecondes) pour des cas d’usage plus larges.

Création de règles d’attente personnalisées

Vérification du statut d’affichage d’un élément

Pour confirmer qu’un élément est visible, vous pouvez vérifier sa présence et ses dimensions :

await page.waitForFunction(() => {
    const element = document.querySelector('.tv-lightweight-charts');
    return element && element.offsetHeight > 0 && element.offsetWidth > 0;
});

Cela garantit que l’élément existe et possède des dimensions visibles dans la page. C’est particulièrement utile pour le contenu dynamique qui nécessite du temps pour se charger correctement [2].

Vérification du texte et des propriétés des éléments

Au-delà des vérifications visuelles, vous pouvez surveiller le contenu textuel ou des propriétés spécifiques des éléments :

// Wait for specific text content
await page.waitForFunction(
    selector => {
        const element = document.querySelector(selector);
        return element && element.textContent.includes('Ready');
    },
    {},
    '.status-message'
);

Pour des vérifications de propriétés plus détaillées, transmettez des arguments supplémentaires :

const expectedValue = 'completed';
const selector = '.status';

await page.waitForFunction(
    (sel, val) => {
        const element = document.querySelector(sel);
        return element && element.getAttribute('data-state') === val;
    },
    {},
    selector,
    expectedValue
);

Combinaison de plusieurs règles d’attente

Après avoir testé des conditions individuelles, vous pouvez les combiner pour des situations plus complexes. Par exemple :

await page.waitForFunction(() => {
    // Check multiple elements and conditions
    const button = document.querySelector('.donate-button');
    const searchBox = document.querySelector('.search-button');

    return button && 
           searchBox && 
           button.offsetHeight > 0 && 
           searchBox.offsetHeight > 0 &&
           !button.disabled;
});

Pour gérer plusieurs éléments dotés de conditions indépendantes, utilisez des combinaisons de Promise [5] :

Modèle d’attenteCas d’usageImplémentation
Tous les élémentsAttendre plusieurs éléments requisPromise.all()
N’importe quel élémentContinuer lorsque le premier élément apparaîtPromise.race()
Logique personnaliséeGérer des vérifications conditionnelles complexesFonctions d’attente combinées

Pour les opérations asynchrones, vous pouvez créer des conditions d’attente avancées :

await page.waitForFunction(
    async () => {
        const response = await fetch('/api/status');
        const data = await response.json();
        return data.isReady && document.querySelector('.content').offsetHeight > 0;
    },
    { polling: 'mutation' }
);

Cette méthode combine la validation des réponses d’API avec des vérifications des éléments du DOM, afin de garantir que les données comme le contenu visuel sont prêts [1].

sbb-itb-23997f1

Méthodes waitForFunction avancées

Écriture de conditions JavaScript complexes

Pour les applications web plus dynamiques, vous pouvez utiliser waitForFunction afin de créer des conditions JavaScript détaillées. Voici un exemple :

await page.waitForFunction(
    (threshold) => {
        const chart = document.querySelector('.tv-lightweight-charts');
        const dataPoints = chart?.querySelectorAll('.data-point');

        return chart && 
               dataPoints?.length > threshold && 
               Array.from(dataPoints).every(point => 
                   point.getBoundingClientRect().height > 0 &&
                   !point.classList.contains('loading')
               );
    },
    { polling: 'mutation' },
    5
);

Ce script garantit que :

  • Le conteneur du graphique existe.
  • Un nombre minimal de points de données est présent.
  • Tous les points de données sont visibles.
  • Aucun point n’est en cours de chargement.

Vous pouvez également combiner des vérifications asynchrones avec des évaluations du DOM pour des situations plus complexes :

await page.waitForFunction(
    async () => {
        // Check if the container is ready
        const container = document.querySelector('.dynamic-content');
        if (!container || container.offsetHeight === 0) return false;

        // Validate API response
        try {
            const response = await fetch('/api/status');
            const data = await response.json();
            return data.isReady && container.children.length > 0;
        } catch {
            return false;
        }
    },
    { 
        polling: 'raf',
        timeout: 30000
    }
);

Cette approche combine les vérifications du DOM avec un appel d’API afin de garantir que l’interface utilisateur et le backend sont synchronisés.

Gestion des délais d’expiration et des erreurs

La gestion des délais d’expiration est essentielle lorsque vous utilisez waitForFunction. Voici un exemple de gestion efficace des délais :

try {
    await page.setDefaultTimeout(60000); // Set a global timeout of 60 seconds

    await page.waitForFunction(
        () => {
            const element = document.querySelector('.dynamic-element');
            return element?.complete === true;
        },
        {
            timeout: 45000, // Specific timeout for this operation
            polling: 'mutation'
        }
    );
} catch (error) {
    if (error.name === 'TimeoutError') {
        console.error('Element state check timed out:', error.message);
        await page.reload(); // Reload page as a fallback
    }
    throw error;
}

Voici un aperçu rapide des stratégies de délai d’expiration :

Stratégie de délai d’expirationCas d’usageConfiguration
Délai par défautOpérations généralespage.setDefaultTimeout()
Délai de navigationChargements de pagepage.setDefaultNavigationTimeout()
Spécifique à l’opérationVérifications détailléesUtilisez l’option timeout dans la méthode
Attente infinieDélais connustimeout: 0

Pour améliorer la gestion des erreurs :

  • Ajustez les paramètres de délai selon la complexité de chaque opération.
  • Utilisez des blocs try-catch pour récupérer proprement après des erreurs.
  • Surveillez l’activité réseau pour identifier les goulots d’étranglement.
  • Mettez en place des actions de secours, comme le rechargement de la page, lorsque des délais d’expiration surviennent.
  • Vérifiez deux fois les sélecteurs pour éviter les délais inutiles.

Ces pratiques contribueront à rendre vos scripts à la fois fiables et efficaces.

Accélérer l’exécution de waitForFunction

Conseils de rapidité et de gestion des ressources

Pour exécuter waitForFunction plus efficacement, privilégiez des stratégies d’attente intelligentes et une bonne gestion des ressources. Utilisez les outils de développement du navigateur pour mesurer les temps de chargement et définir des délais précis.

// Optimize waiting with a networkidle strategy
await page.goto('https://example.com', {
    waitUntil: 'networkidle2',
    timeout: 30000
});

// Combine checks in a single evaluate call
await page.evaluate(() => {
    const element = document.querySelector('.dynamic-content');
    const isVisible = element?.offsetHeight > 0;
    const hasData = element?.children.length > 0;
    return isVisible && hasData;
});

Pour réduire l’utilisation des ressources :

  • Bloquez les ressources inutiles telles que les images ou les polices.
  • Utilisez waitForSelector ou waitForFunction au lieu de waitForTimeout, désormais obsolète.
  • Combinez plusieurs vérifications dans un seul appel evaluate afin de réduire les communications entre le navigateur et Node.js.
StratégieImpact sur les performancesMeilleur cas d’usage
networkidle2ModéréNavigation sur une page
waitForSelectorRapideVérifications d’un seul élément
waitForFunctionVariableConditions complexes
evaluate combinéLe plus rapideVérifications de plusieurs éléments

Ces méthodes permettent de résoudre des goulots d’étranglement courants, abordés dans la section suivante.

Résolution des problèmes courants

Les problèmes de performances proviennent souvent de modèles d’attente inefficaces. Voici comment les gérer :

Problèmes de sélecteurs
Des sélecteurs trop rigides peuvent provoquer des échecs. Simplifiez-les pour améliorer la fiabilité :

// Avoid rigid selectors like this
await page.waitForSelector('div.container > div:nth-child(2) > span.text-red');

// Use a more flexible approach
await page.waitForFunction(
    () => document.querySelector('.text-red')?.offsetParent !== null
);

Gestion des ressources
Gérez les ressources et évitez les délais inutiles :

try {
    await page.waitForFunction(
        () => document.readyState === 'complete' &&
              performance.now() > 1000
    );
} catch (error) {
    console.error('Page load timeout:', error.message);
}

« Puppeteer dispose d’une architecture pilotée par les événements, ce qui élimine une grande partie de l’instabilité potentielle. Les appels sleep[undefined] inutiles n’ont pas leur place dans les scripts Puppeteer. » — readme de Puppeteer [6]

Encadrez toujours les méthodes d’attente dans des blocs try...catch afin de gérer les erreurs proprement et de proposer des solutions de secours. Cette approche garantit la robustesse et la fiabilité de vos scripts.

Cas d’usage courants des règles d’attente personnalisées

Chargement des produits d’une boutique en ligne

S’assurer que les produits se chargent correctement est indispensable pour collecter des données précises. Utilisez une règle d’attente personnalisée afin de suspendre l’exécution jusqu’au chargement complet des éléments de produit :

await page.waitForFunction(() => {
    const products = document.querySelectorAll('.product-card');
    return products.length > 0 && all images and prices fully load;
});

Pour davantage de précision, vous pouvez utiliser cette approche :

await page.waitForFunction(() => {
    const productDetails = document.querySelector('.product-details');
    return productDetails && 
           productDetails.offsetHeight > 0 && 
           productDetails.querySelector('.inventory-status') !== null;
}, {timeout: 30000});

Cela garantit que votre script attend le chargement de tous les éléments nécessaires, améliorant ainsi la fiabilité de la collecte de données dans les cas d’usage e-commerce.

Chargement de contenu dans les applications web modernes

Les applications web dynamiques nécessitent souvent des conditions d’attente spécifiques pour gérer le chargement du contenu. Par exemple, vous pouvez attendre qu’un élément particulier devienne entièrement visible :

await page.waitForFunction(() => {
    const element = document.querySelector('.tv-lightweight-charts');
    return element && element.offsetHeight > 0 && element.offsetWidth > 0;
});

Si plusieurs sections doivent être chargées, combinez les conditions comme suit :

await page.waitForFunction(() => {
    const contentLoaded = document.querySelector('.content').children.length > 0;
    const dataUpdated = document.body.textContent.includes('Last updated:');
    return contentLoaded && dataUpdated;
}, {polling: 1000});

Cette méthode permet de garantir que vos scripts d’automatisation interagissent de manière fluide avec le contenu dynamique.

Détection des messages d’erreur de formulaire

La détection des erreurs de formulaire repose sur une logique similaire aux vérifications de visibilité des éléments. Voici comment surveiller les messages d’erreur :

await page.waitForFunction(() => {
    const errorContainer = document.querySelector('.error-messages');
    const hasErrors = errorContainer?.children.length > 0;
    const isVisible = errorContainer?.offsetParent !== null;
    return hasErrors && isVisible;
});

Vous pouvez également suivre différents états de validation des formulaires à l’aide de conditions d’attente spécifiques :

Type de validationCondition d’attenteCas d’usage
Erreurs de champVérifier la présence d’une classe d’erreurValidation d’un champ individuel
Erreurs de formulaire globalesSurveiller le conteneur d’erreursÉtat global du formulaire
Messages de réussiteSurveiller les affichages de confirmationFinalisation de l’envoi
États de chargementSuivre l’état du bouton d’envoiIndication de traitement

Conclusion

Points clés à retenir

La méthode waitForFunction de Puppeteer évalue des conditions JavaScript jusqu’à ce qu’elles renvoient true, offrant un contrôle précis des interactions avec les pages dynamiques [3].

Voici quelques avantages clés de waitForFunction :

  • Évaluation flexible : gère les fonctions asynchrones pour surveiller des états de page complexes [3].
  • Intégration du contexte : permet de transmettre directement des arguments Node.js au contexte du navigateur [3].
  • Logique personnalisée : permet une automatisation adaptée à des conditions de page spécifiques [2].

Cette approche est particulièrement utile lorsque les méthodes d’attente standard ne suffisent pas. Par exemple, dans les applications monopage avancées, plusieurs éléments peuvent se charger simultanément ou certains états JavaScript peuvent devoir être confirmés avant de poursuivre.

Puppeteer et Latenode en action

Latenode tire parti de waitForFunction pour améliorer l’automatisation des workflows. En intégrant cette méthode, Latenode a créé un nœud de surveillance personnalisé qui vérifie les statuts des sites web et capture des captures d’écran lorsque certaines conditions ne sont pas satisfaites [7].

Voici un exemple de l’utilisation de waitForFunction par Latenode afin de garantir que les éléments critiques sont entièrement affichés avant de poursuivre :

await page.waitForFunction(() => {
    const element = document.querySelector('.tv-lightweight-charts');
    return element && element.offsetHeight > 0 && element.offsetWidth > 0;
});

Cet extrait attend qu’un élément portant la classe .tv-lightweight-charts apparaisse non seulement dans le DOM, mais soit également entièrement affiché [2].

Pour obtenir les meilleurs résultats avec Latenode et Puppeteer :

  • Définissez des valeurs de délai appropriées à l’aide de page.setDefaultTimeout().
  • Utilisez des blocs try-catch pour une gestion robuste des erreurs.
  • Suivez les temps d’exécution afin d’affiner vos conditions d’attente.

References

FAQ

Frequently Asked Questions

waitForFunction évalue régulièrement une condition JavaScript dans le contexte du navigateur jusqu’à ce qu’elle renvoie une valeur véridique, puis se résout. Utilisez-la lorsque waitForSelector standard ne suffit pas pour du contenu dynamique, des états DOM personnalisés ou des vérifications combinant API et DOM.

Cela vous a aidé ? Partagez-le →

Écrit par

Vasiliy Datsenko

Responsable du support client

Vasiliy Datsenko est responsable du support client chez Latenode et un rédacteur en automatisation axé sur les produits. Son travail relie les conversations clients, la recherche sur l'automatisation des flux de travail, les cas d'utilisation de l'IA et la formation pratique sur les produits pour les équipes cherchant à automatiser des processus métier réels.

Profil de l'auteur →

Vérifié par

Oleg Zankov

PDG de Latenode, expert en no-code

Avec une philosophie ancrée dans l'innovation, la résolution de problèmes et l'expérience utilisateur, je me consacre à donner aux équipes les moyens de créer des intégrations sur mesure et d'automatiser les workflows avec facilité et efficacité. Fort d'une riche expérience en développement commercial, entrepreneurship technologique et développement logiciel, j'ai reconnu le besoin d'une solution d'intégration plus accessible, évolutive et adaptable. Ainsi est né Latenode.com. Grâce à notre plateforme, les entreprises peuvent exploiter la puissance de la technologie sans nécessiter de compétences approfondies en codage. Passionné par la création d'un avenir où la technologie nous sert, et non l'inverse, ma mission est de simplifier les processus complexes. Je crois en la démocratisation de la technologie et en dotant les équipes des outils nécessaires pour innover, croître et réussir dans un monde de plus en plus numérique.

Profil de l'auteur →

Continuer la lecture