Movatterモバイル変換


[0]ホーム

URL:


  1. Web
  2. Les API Web
  3. Window
  4. setTimeout()

Cette page a été traduite à partir de l'anglais par la communauté.Vous pouvez contribuer en rejoignant la communauté francophone sur MDN Web Docs.

View in EnglishAlways switch to English

setTimeout()

Baseline Widely available *

Cette fonctionnalité est bien établie et fonctionne sur de nombreux appareils et versions de navigateurs. Elle est disponible sur tous les navigateurs depuis juillet 2015.

* Certaines parties de cette fonctionnalité peuvent bénéficier de prise en charge variables.

La méthode globalesetTimeout() permet de définir un minuteur qui exécute une fonction ou un code donné après la fin du délai indiqué.

Syntaxe

js
setTimeout(code);setTimeout(code, delay);setTimeout(functionRef);setTimeout(functionRef, delay);setTimeout(functionRef, delay, param1);setTimeout(functionRef, delay, param1, param2);setTimeout(functionRef, delay, param1, param2, /* ... ,*/ paramN);

Paramètres

functionRef

Unefonction à exécuter lorsque le délai du minuteur est expiré.

code

Une syntaxe alternative qui permet d'inclure une chaîne de caractères plutôt qu'une fonction. Le code contenu est compilé et exécuté lorsque le minuteur expire. Cette syntaxe estdéconseillée pour les mêmes raisons qu'eval() et représente un risque de sécurité.

delayFacultatif

La durée, exprimée en millisecondes, que le minuteur devrait attendre avant l'exécution de la fonction indiquée. Si ce paramètre est absent, c'est 0 qui est utilisé comme valeur par défaut, indiquant que la fonction doit être exécutée au plus vite, c'est-à-dire au prochain cycle d'évènements.

Que le paramètre soit fourni ou non, la durée attendue avant l'exécution peut être plus longue que le nombre de millisecondes exprimées, voirles raisons pour lesquelles la durée effective est plus longue ci-après.

On notera également que si la valeur n'est pas un nombre,une conversion implicite est effectuée pour transformer la valeur en un nombre. Voirun exemple de conversion de valeur non-numérique pour la durée ci-après.

param1, …,paramNFacultatif

Des arguments additionnels qui sont passés à la fonction donnée par l'argumentfunction.

Valeur de retour

Un entier positiftimeoutID qui identifie le minuteur créé par l'appel àsetTimeout(). Cette valeur peut être passée àclearTimeout() pour annuler le minuteur.

Une même valeur detimeoutID ne sera jamais réutilisée par un appel ultérieur àsetTimeout() ousetInterval() sur le même objet (que ce soit une fenêtre ou unworker). Toutefois, des objets différents utilisent des ensembles distincts d'identifiants.

Description

Les minuteurs sont annulés grâce à la fonctionclearTimeout().

Pour appeler une fonction de façon répétée (toutes lesN millisecondes), on utilisera plutôtsetInterval().

Conversion de valeur non-numérique pour la durée

LorsquesetTimeout() est appelée avec une valeur du paramètredelay qui n'est pas un nombre, uneconversion de type sera effectuée implicitement pour convertir la valeur en nombre. Ainsi, dans l'exemple qui suit, le code fait l'erreur d'utiliser la valeur"1000" qui est une chaîne de caractères, plutôt que le nombre1000, mais cela fonctionne, car la chaîne est transformée implicitement dans la valeur numérique1000, et la fonction est donc exécutée après 1 seconde.

js
setTimeout(() => {  console.log("Retardée d'une seconde.");}, "1000");

Toutefois, dans de nombreux cas, la conversion implicite peut mener à des résultats inattendus voire surprenants. Par exemple, lorsque le code qui suit est exécuté, la chaîne de caractères"1 seconde" est en fait transformée dans le nombre0, et le code est donc exécuté immédiatement.

js
setTimeout(() => {  console.log("Retardée d'une seconde.");}, "1 seconde");

Aussi, on veillera à ne pas utiliser de chaîne de caractères pour le paramètredelay et à utiliser uniquement des nombres :

js
setTimeout(() => {  console.log("Retardée d'une seconde.");}, 1000);

Fonctionnement avec les fonctions asynchrones

setTimeout() est une fonction asynchrone, ce qui signifie que la fonction passée en argument ne bloquera pas l'exécution des autres fonctions de la pile d'appels. Autrement dit, on ne peut pas utilisersetTimeout() afin de créer une pause avant que la prochaine fonction de la pile soit déclenchée.

Prenons cet exemple :

js
setTimeout(() => {  console.log("Voici le premier message");}, 5000);setTimeout(() => {  console.log("Voici le second message");}, 3000);setTimeout(() => {  console.log("Voici le troisième message");}, 1000);// Produira ceci dans la console :// Voici le troisième message// Voici le second message// Voici le premier message

On voit ici que la première fonction ne crée pas une pause de 5 secondes que la deuxième fonction soit appelée. La première fonction est appelée par le moteur dès lors que 5 secondes sont écoulées. Pendant ce délai, le reste des instructions continue de s'exécuter et la deuxième fonction est appelée par le moteur dès que 3 secondes se sont écoulées. Juste après, il en va de même après la troisième fonction. Le délai de 1 seconde étant écoulé d'abord, c'est la troisième fonction qui est exécutée d'abord, puis la seconde et enfin la première.

Pour créer une séquence d'opérations où une fonction se déclenche uniquement après qu'une autre fonction ait terminé, on utilisera plutôtles promesses.

Le problème dethis

Lorsqu'on passe une méthode àsetTimeout(), elle est appelée avec une valeur dethis qui peut être différente de celle attendue. Ce problème général est détaillé dansla référence JavaScript.

Le code exécuté parsetTimeout() est appelé par un contexte d'exécution séparé de la fonction depuis laquellesetTimeout() a été appelé. Les règles usuelles pour la définition du mot-cléthis s'appliquent et sithis n'est pas défini lors de l'appel ou avecbind(), sa valeur par défaut sera l'objetwindow (ouglobal). Il ne s'agira pas de la même valeur dethis qu'au sein de la fonction qui a appelésetTimeout().

Prenons l'exemple suivant :

js
const monTableau = ["zéro", "un", "deux"];monTableau.maMethode = function (sPropriete) {  console.log(arguments.length > 0 ? this[sPropriete] : this);};monTableau.maMethode(); // affiche "zéro,un,deux"monTableau.maMethode(1); // affiche "un"

Cela fonctionne, car, lorsquemaMethode est appelée,this vautmonTableau et, au sein de la fonction,this[sPropriete] est donc équivalent àmonTableau[sPropriete]. Toutefois, si on écrit ceci :

js
setTimeout(monTableau.maMethode, 1.0 * 1000); // affiche "[object Window]" après 1 secondesetTimeout(monTableau.maMethode, 1.5 * 1000, "1"); // affiche "undefined" après 1.5 secondes

La fonctionmonTableau.maMethode est passée àsetTimeout, et lorsqu'elle est appelée, la valeur dethis n'est pas définie et vautwindow par défaut.

Il n'y a pas d'argumentthisArg poursetTimeout (comme on peut en voir pourforEach() etreduce(). Comme indiqué après, utilisercall() ne fonctionne pas non plus.

js
setTimeout.call(monTableau, monTableau.maMethode, 2.0 * 1000); // erreursetTimeout.call(monTableau, monTableau.maMethode, 2.5 * 1000, 2); // erreur également

Solutions

Utiliser une fonction englobante

Une méthode pour résoudre ce problème consiste à englober la méthode dans une fonction afin quethis ait la valeur attendue :

js
setTimeout(function () {  monTableau.maMethode();}, 2.0 * 1000);// affiche "zéro,un,deux" après 2 secondessetTimeout(function () {  monTableau.maMethode("1");}, 2.5 * 1000);// affiche "un" après 2.5 secondes

La fonction englobante peut être une fonction fléchée :

js
setTimeout(() => {  monTableau.maMethode();}, 2.0 * 1000);// affiche "zéro,un,deux" après 2 secondessetTimeout(() => {  monTableau.maMethode("1");}, 2.5 * 1000);// affiche "un" après 2.5 secondes
Utiliserbind()

On peut aussi utiliser la fonctionbind() afin de fixer la valeur dethis pour tous les appels à une fonction donnée :

js
const monTableau = ["zéro", "un", "deux"];const maMethodeLiee = function (sPropriete) {  console.log(arguments.length > 0 ? this[sPropriete] : this);}.bind(monTableau);maMethodeLiee();// affiche "zéro,un,deux" car 'this' est lié à monTableau// dans la fonctionmaMethodeLiee(1);// affiche "un"setTimeout(maMethodeLiee, 1.0 * 1000);// Affiche "zéro,un,deux" après 1 seconde grâce à la liaisonsetTimeout(maMethodeLiee, 1.5 * 1000, "1");// Affiche "un" après 1.5 secondes

Passer une chaîne de caractères pour les instructions à exécuter

Lorsqu'on passe une chaîne de caractères plutôt qu'une fonction àsetTimeout(), cela expose aux mêmes problèmes que d'utilisereval().

js
// À ne pas fairesetTimeout("console.log('Hello World!');", 500);
js
// On privilégiera cette formesetTimeout(function () {  console.log("Hello World!");}, 500);

Une chaîne de caractères passée àsetTimeout() est évaluée dans le contexte global et les symboles locaux au contexte oùsetTimeout() a été appelée ne seront plus disponibles lorsque la chaîne de caractères sera évaluée comme du code.

Raisons pour lesquelles la durée effective est plus longue

Plusieurs raisons peuvent expliquer que la durée effective d'un minuteur soit plus longue que celle attendue. Dans cette section, nous couvrirons les raisons les plus communes.

Minuteurs imbriqués

Comme indiqué dansle standard HTML, les navigateurs appliqueront un délai minimum de 4 millisecondes lorsqu'un appel imbriqué àsetTimeout a été planifié 5 fois.

On peut observer ce comportement dans l'exemple qui suit, dans lequel on imbrique un appel àsetTimeout() avec une durée spécifiée à0 milliseconde. Ensuite, on affiche la durée effective lorsque le gestionnaire est appelé. On peut voir que, pour les 4 premières fois, la durée effective est de 0 milliseconde environ et qu'après, elle passe à environ 4 millisecondes :

html
<button>Exécuter</button><pre>Précédent    courant    durée</pre><div></div>
js
let last = 0;let iterations = 10;function timeout() {  // Enregistrer l'instant de l'appel  logline(new Date().getMilliseconds());  // Tant qu'on n'a pas fini, planifier le prochain appel  if (iterations-- > 0) {    setTimeout(timeout, 0);  }}function run() {  // Nettoyer le journal  const log = document.querySelector("#log");  while (log.lastElementChild) {    log.removeChild(log.lastElementChild);  }  // Initialiser le nombre d'itérations et l'horodatage  // de départ  iterations = 10;  last = new Date().getMilliseconds();  // Démarrer le minuteur  setTimeout(timeout, 0);}function pad(number) {  return number.toString().padStart(3, "0");}function logline(now) {  // Afficher le dernier horodatage, le nouveau, et la  // différence  const newLine = document.createElement("pre");  newLine.textContent = `${pad(last)}           ${pad(now)}          ${    now - last  }`;  document.getElementById("log").appendChild(newLine);  last = now;}document.querySelector("#run").addEventListener("click", run);

Minuteurs dans les onglets inactifs

Afin de réduire la charge (et la consommation énergétique associée) des onglets en arrière-plan, les navigateurs appliqueront un délai minimum sur les onglets inactifs. Ceci peut ne pas s'appliquer si la page joue du son avec l'API Web Audio etAudioContext.

Certains aspects spécifiques de cette règle dépendent des navigateurs :

  • Firefox Desktop et Chrome appliquent une durée minimale de 1 seconde pour les onglets inactifs.
  • Firefox pour Android applique une durée minimale de 15 minutes pour les onglets inactifs et peut les décharger complètement.
  • Firefox ne limite pas un onglet inactif si celui-ci contient unAudioContext.

Limitation des scripts de pistage

Firefox applique certaines limitations pour les scripts qu'il reconnaît comme scripts de pistage. Lors de l'exécution dans un onglet actif, le délai minimal est de 4ms. Pour les onglets en arrière-plan, ce délai passe à 10 seconds et s'applique 30 secondes après que le chargement initial du document a eu lieu.

Voirla page d'information sur la protection contre le pistage (en anglais) pour plus de détails.

Ordonnancement des autres tâches

Le minuteur peut également se déclencher plus tard si le système d'exploitation ou le navigateur est occupé à d'autres tâches.

Par exemple, on notera que la fonction passée en argument desetTimeout() ne peut pas être exécutée avant que lethread qui appellesetTimeout() ait terminé son exécution. On aura donc :

js
function toto() {  console.log("toto a été appelée");}setTimeout(toto, 0);console.log("Après setTimeout()");

Affichera ce qui suit dans la console :

Après setTimeout()toto a été appelée

En effet, même sisetTimeout() a été appelé avec un délai à zéro, la fonction correspondante est placée dans une queue et son exécution est planifiée pour le prochain cycle disponible et pas immédiatement.

Le code en cours d'exécution doit terminer avant que les fonctions placées dans la queue puissent être exécutées. C'est pour cela qu'on a cet ordre d'exécution, qui peut ne pas être celui qu'on attendait.

Report des minuteurs pendant le chargement de la page

Firefox diffèrera le déclenchement des minuteurs lorsque l'onglet actuel est en train de charger. Le déclenchement est reporté jusqu'à ce que le fil d'exécution principal soit considéré comme inactif (idle) (à la façon dewindow.requestIdleCallback()), ou jusqu'à ce que l'évènementload soit déclenché.

Pages d'arrière-plan des WebExtensions et minuteurs

Pour lesWebExtensions,setTimeout() ne fonctionne pas de façon sûre. Il faut privilégier l'APIalarms pour le développement d'extensions.

Valeur maximale pour le délai

Les navigateurs comme Internet Explorer, Chrome, Safari, et Firefox stockent le délai sous la forme d'un entier signé sur 32 bits. Aussi, il y a un dépassement des limites lorsqu'on indique un délai supérieur à 2 147 483 647 ms (ce qui correspond à 24,8 jours), et le résultat est un minuteur qui est exécuté immédiatement.

Exemples

Définir et annuler des minuteurs

Dans l'exemple qui suit, on a deux boutons simples sur une page web qui sont reliés aux fonctionssetTimeout() etclearTimeout(). Appuyer sur le premier bouton déclenchera un minuteur qui affichera un message après deux secondes et enregistrera l'identifiant du minuteur pour que celui-ci soit utilisé avecclearTimeout(). En appuyant sur le deuxième bouton, on peut annuler le minuteur.

HTML

html
<button>  Afficher un message après deux secondes</button><button>  Annuler le message avant qu'il apparaisse</button><div></div>

JavaScript

js
let timeoutID;function setOutput(outputContent) {  document.querySelector("#output").textContent = outputContent;}function delayedMessage() {  setOutput("");  timeoutID = setTimeout(setOutput, 2 * 1000, "C'était lent !");}function clearMessage() {  clearTimeout(timeoutID);}
#output {  padding: 0.5rem 0;}

Résultat

Voir aussil'exempleclearTimeout().

Spécifications

Specification
HTML
# dom-settimeout-dev

Compatibilité des navigateurs

Voir aussi

Help improve MDN

Learn how to contribute

Cette page a été modifiée le par lescontributeurs du MDN.


[8]ページ先頭

©2009-2026 Movatter.jp