Maison  >  Article  >  interface Web  >  SetTimeout n'est pas la même chose que vous le pensez

SetTimeout n'est pas la même chose que vous le pensez

WBOY
WBOYoriginal
2024-08-06 00:43:01616parcourir

Lorsque les développeurs rencontrent pour la première fois setTimeout en JavaScript, cela semble souvent être un outil simple pour retarder l'exécution d'une fonction. Cependant, comprendre comment setTimeout interagit avec le runtime JavaScript et la boucle d'événements peut révéler un comportement inattendu, en particulier dans certaines conditions. Et ce n'est pas seulement setTimeout ; des complexités similaires surviennent également avec setInterval et d'autres fonctions asynchrones.

La boucle événementielle : un bref aperçu
JavaScript est monothread, ce qui signifie qu'il ne peut exécuter qu'un seul morceau de code à la fois. Malgré cela, la boucle d'événements permet à JavaScript d'effectuer des opérations non bloquantes. Il y parvient en déchargeant des tâches telles que des minuteries, des requêtes réseau ou des opérations d'E/S vers le navigateur ou l'API Node.js. Une fois ces tâches terminées, leurs fonctions de rappel sont remises en file d'attente dans la boucle d'événements pour exécution.

SetTimeout is Not the Same as You Think

Comment fonctionne setTimeout
Lorsque vous appelez setTimeout, vous demandez au moteur JavaScript d'exécuter une fonction après une période spécifiée. Cela se fait en ajoutant la fonction de rappel à la file d'attente de la boucle d'événements. Cependant, le délai spécifié est le temps minimum que le moteur doit attendre avant d'ajouter le rappel à la file d'attente, et non un temps d'exécution garanti. Voici comment cela fonctionne en détail :

  1. Appel initial : lorsque setTimeout est invoqué avec une fonction de rappel et un délai, le moteur JavaScript l'enregistre dans l'environnement API Web fourni par le navigateur ou Node.js.

  2. Timer : L'API Web démarre une minuterie pour le délai spécifié. Pendant cette période, la pile d'appels principale continue d'exécuter tout code synchrone qui suit l'appel setTimeout.

  3. Callback Queuing : Une fois le délai expiré, l'API Web n'exécute pas immédiatement le rappel. Au lieu de cela, il déplace la fonction de rappel vers la file d'attente des événements.

  4. Boucle d'événements : La boucle d'événements, qui surveille en permanence la pile d'appels et la file d'attente des événements, entre en jeu. Si la pile d'appels est vide, ce qui signifie qu'aucune tâche n'est en cours d'exécution, la boucle d'événements prend la première fonction de la file d'attente d'événements et la pousse sur la pile d'appels pour exécution.

  5. Exécution : La fonction de rappel est finalement exécutée lorsqu'elle atteint le sommet de la pile d'appels.

Il est important de noter que si la pile d'appels est occupée par d'autres tâches à l'expiration du délai, il peut y avoir des délais supplémentaires avant l'exécution de la fonction de rappel. En effet, la boucle d'événements doit attendre que la pile d'appels soit vide avant de pouvoir traiter la fonction de rappel à partir de la file d'attente d'événements.

SetTimeout is Not the Same as You Think


Le problème du blocage
Un malentendu courant consiste à supposer que setTimeout exécutera toujours le rappel après le délai exact spécifié. Si la boucle d'événement est bloquée par du code synchrone, comme une boucle infinie ou un calcul de longue durée, le rappel ne sera exécuté que lorsque la boucle d'événement sera libre.

Considérez le scénario suivant :

console.log('Program started at: ' + new Date().toLocaleTimeString());

const programStartTime = Date.now();

function blockExecutionForThirtySeconds() {
  while (true) {
    const currentTime = Date.now();
    if (currentTime - programStartTime > 30000) {
      console.log('Blocking execution completed after 30 seconds...');
      return true;
    }
  }
}

console.log('Setting setTimeout for 1 second.');
setTimeout(() => {
  console.log('setTimeout executed after 30 seconds instead of 1 second: ' + new Date().toLocaleTimeString());
}, 1000);

blockExecutionForThirtySeconds();

Dans cet exemple, la fonction blockExecutionForThirtySeconds bloque la boucle d'événement avec une boucle infinie qui s'exécute pendant 30 secondes. Même si setTimeout est configuré pour s'exécuter après 1 seconde, il ne s'exécutera qu'une fois blockExecutionForThirtySeconds terminé, soit après 30 secondes.

SetTimeout is Not the Same as You Think

Implications dans le monde réel
Comprendre ce comportement est crucial pour les développeurs, en particulier lors de l'écriture de code impliquant des délais d'attente, des intervalles ou un traitement asynchrone. Une mauvaise compréhension du fonctionnement de setTimeout peut entraîner des problèmes de performances et des bogues difficiles à retracer. Si un morceau de code effectue des calculs lourds ou des tâches de longue durée et bloque la boucle d'événements, tous les rappels setTimeout, résolutions de promesses et autres opérations asynchrones seront retardés jusqu'à ce que la boucle d'événements soit libre.

Conclusion
setTimeout est un outil puissant en JavaScript pour retarder l'exécution du code, mais il est important d'en comprendre les nuances. Le délai spécifié est le temps d'attente minimum avant que la fonction puisse être mise en file d'attente pour exécution. Le temps d'exécution réel dépend de l'état de la boucle d'événements. La maîtrise des opérations asynchrones et de la gestion des boucles d'événements est essentielle pour écrire des applications JavaScript efficaces et réactives.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Article précédent:JavaScript en inuteArticle suivant:JavaScript en inute