Comment faire un yield au fil principal

Faites un yield au fil principal pour améliorer la réactivité de la page

Arjen Karel Core Web Vitals Consultant
Arjen Karel - linkedin
Last update: 2026-02-07

Faire un yield au fil principal

Imaginez un film romantique. Le décor est un petit marché français au centre d'un petit village. Les rues sont remplies de couples buvant du café, mangeant des croissants et achetant des fleurs. Maintenant, imaginez ce qui se passe lorsqu'un seul vendeur peut servir un client à la fois alors que tous les autres doivent attendre leur tour. Le boulanger est submergé de demandes, des disputes éclatent chez le fleuriste et la promenade romantique se transforme en une attente frustrante.

Eh bien...  c'est un peu ce qui se passe sur un site web lorsque les choses deviennent trop chargées.

L'importance du Yielding

Le fil principal d'un navigateur gère tous les processus importants et planifie toutes les tâches importantes (analyse HTML et CSS, exécution du code JavaScript, gestion des événements d'entrée comme les clics et les défilements, et le rendu visuel).

Le fil principal d'un navigateur fonctionne sur un modèle à thread unique. Cela signifie qu'il ne peut effectuer qu'une seule tâche à la fois. Lorsqu'une tâche (généralement l'exécution JavaScript ou le rendu) commence à s'exécuter, le navigateur exécutera cette tâche 'jusqu'à son terme' et ne s'arrêtera pas avant qu'elle ne soit terminée. Cela signifie qu'il ne planifiera ni n'effectuera aucune autre tâche tant que la tâche précédente n'est pas prête. C'est ce qu'on appelle 'bloquer le fil principal'. Bloquer le fil principal est un problème lorsque les visiteurs interagissent avec une page car la page ne répondra pas pendant le temps de blocage.

Une façon de corriger le blocage du fil principal est de 'Faire un yield au fil principal'. Le Yielding est une technique où les tâches longues sont décomposées en plusieurs tâches plus petites  pour permettre au fil principal de gérer des tâches plus importantes (comme les entrées utilisateur). 

Tâches longues et période de blocage : Lorsqu'une tâche prend plus de 50 millisecondes, elle est classée comme une tâche longue, et tout ce qui dépasse ce seuil de 50 millisecondes est connu sous le nom de 'période de blocage' de la tâche. Découper ces tâches longues en morceaux plus petits permet au navigateur de rester réactif, même lors du traitement d'opérations gourmandes en calcul.

Anciennes stratégies de yielding

Avant la nouvelle [url=https://developer.mozilla.org/en-US/docs/Web/API/Prioritized_Task_Scheduling_API]Prioritized Task Scheduling API[/url], il y avait 4 façons de faire un yield au fil principal. Toutes ont leurs limitations et préoccupations !

  • setTimeout() : La stratégie la plus courante, setTimeout() fonctionne en exécutant du code dans une fonction de rappel après un délai spécifié. En définissant un délai (ou timeout) de 0, setTimeout() ajoute la tâche à la fin de la file d'attente, permettant aux autres tâches de s'exécuter en premier. Un problème majeur est que setTimeout() n'est pas conçu pour une planification précise car les tâches ne peuvent être poussées qu'à la fin de la file d'attente.
  • requestAnimationFrame() : requestAnimationFrame() fonctionne en mettant en file d'attente une fonction à exécuter avant le prochain rafraîchissement (repaint) du navigateur. requestAnimationFrame() est souvent combiné avec setTimeout() pour s'assurer que les fonctions de rappel soient planifiées après la prochaine mise à jour de la mise en page.
  • requestIdleCallback() : Cette méthode est la mieux adaptée pour les tâches non critiques et de faible priorité qui peuvent être exécutées pendant les temps d'arrêt du navigateur. Bien qu'elle aide à garder le fil principal libre pour des tâches plus cruciales, requestIdleCallback() souffre d'une limitation significative : il n'y a aucune garantie que les tâches planifiées s'exécuteront rapidement (ou même jamais !!!), surtout sur un fil principal chargé.
  • isInputPending() : isInputPending() fonctionne en vérifiant les entrées utilisateur en attente et en ne faisant un yield que si une entrée est détectée. isInputPending() peut être utilisé conjointement avec d'autres fonctions de yielding pour éviter un yielding inutile. Malheureusement, il peut renvoyer de faux négatifs et ne répond pas au besoin de faire un yield pour d'autres tâches critiques pour la performance comme les animations.

Présentation de : scheduler.yield()

Les limitations de ces 4 méthodes ont été une préoccupation pour l'équipe Chrome, surtout avec de nombreux sites échouant à la métrique Interaction to Next Paint. Pour corriger cela et aider, l'équipe Chrome a construit de nouvelles API qui donnent un contrôle granulaire sur la planification JavaScript.

Découvrez scheduler.yield() ! Avec window.scheduler.yield(), les développeurs peuvent efficacement faire un yield au fil principal immédiatement sans réorganiser l'ordre des tâches ni créer de complexité supplémentaire.

Utiliser Scheduler.yield() efficacement

Plongeons dans le code et explorons comment tirer parti de scheduler.yield() comme il se doit ! Avant de commencer à utiliser scheduler.yield(), il est important de vérifier la compatibilité du navigateur car c'est une fonctionnalité expérimentale et tous les navigateurs ne la supportent pas encore. 

Exemple de code

function yieldToMain() {
  if ('scheduler' in window && 'yield' in window.scheduler) {
    return window.scheduler.yield();
  }
  return new Promise((resolve) => {
    setTimeout(resolve, 0);
  });
}

La fonction yieldToMain() est le cœur du contrôle du yielding vers le fil principal. Elle vérifie d'abord que window.scheduler et window.scheduler.yield existent tous les deux. Si c'est le cas, nous pouvons utiliser window.scheduler.yield en toute sécurité. Si  window.scheduler.yield n'est pas supporté, le code se replie sur setTimeout.

Version plus courte et prête pour la production

Ou utilisez cette version plus courte et prête pour la production qui utilise l'opérateur ternaire :

/* or shorter and production ready: */
function yieldToMain(){
  return"scheduler"in window&&"yield"in window.scheduler?
  window.scheduler.yield():new Promise(e=>{setTimeout(e,0)})
}

Exemple concret : Améliorer la recherche avec yieldToMain() :

Voyons comment nous pouvons utiliser yieldToMain() pour améliorer l'expérience de recherche pour vos utilisateurs :

La fonction handleSearch() démontre comment yieldToMain() peut être utilisé efficacement. Elle met d'abord à jour le contenu du bouton pour fournir un retour immédiat indiquant qu'une recherche est en cours. Vous pouvez utiliser yieldToMain() ici pour permettre au navigateur de mettre à jour la mise en page.

Ensuite, fetchData() récupère les données de recherche, et updateHTML(data) affiche les résultats. Un autre  yieldToMain() assure une mise à jour rapide de la mise en page (car nous ne pouvons jamais être sûrs qu'il n'y a pas d'autres écouteurs d'événements en attente après cette tâche).  Enfin, d'autres tâches moins importantes sont planifiées pendant le temps d'inactivité du navigateur. Notez que je n'ai pas fait de yield au fil principal ici car requestIdleCallback() ne s'exécutera que lorsque le fil principal sera inactif.

async function handleSeach(){
 /* quickly update the button content after submitting*/
 updateButtontoPending();

 /* Yield to Main */
 await yieldToMain();

 /* fetch data and update html*/
 const data = await fetchData();
 updateHTML(data);

 /* Yield to Main again */
 await yieldToMain();

 /* some function should only run during browser idle time*/
 requestIdleCallback(sendDataToAnalytics);
}

Pourquoi scheduler.yield() est tout simplement meilleur

Contrairement à setTimeout(), qui ajoute les tâches différées à la fin de la file d'attente des tâches, scheduler.yield() ne fait que mettre en pause la file d'attente javascript et les tâches en pause restent à l'avant de la file d'attente, garantissant qu'elles sont exécutées dès que possible après que les tâches de priorité supérieure (comme la gestion des rappels d'entrée) ont été terminées. Ce comportement de "front-of-queue" résout le plus gros problème des anciennes méthodes de yielding. Et les développeurs peuvent maintenant 'faire un yield au fil principal' sans risquer que leurs tâches importantes soient retardées par d'autres tâches moins importantes.

Un autre avantage de scheduler.yield() est qu'il est conçu pour fonctionner avec la Prioritized Task Scheduling API comme scheduler.postTask(), ce qui permet de prioriser les tâches en fonction de leur importance. Cette combinaison de fonctionnalités fournit aux développeurs une boîte à outils puissante pour optimiser la réactivité et les performances de leurs applications web.


Comment faire un yield au fil principal Core Web Vitals Comment faire un yield au fil principal