Fermer

juillet 7, 2020

Exemples de fonctions JavaScript setTimeout () –


setTimeout est une fonction JavaScript native (bien qu'elle puisse être utilisée avec une bibliothèque telle que jQuery, comme nous le verrons plus loin), qui appelle une fonction ou exécute un extrait de code après un délai spécifié (en millisecondes) ). Cela peut être utile si, par exemple, vous souhaitez afficher une fenêtre contextuelle après qu'un visiteur a parcouru votre page pendant un certain temps, ou si vous souhaitez un court délai avant de supprimer un effet de survol d'un élément (dans le cas où l'utilisateur accidentellement

 set_timeout_2-01

Cet article populaire a été mis à jour en 2020.

Exemple de base setTimeout

Pour illustrer le concept, la démo suivante affiche une fenêtre contextuelle, deux secondes après avoir cliqué sur le bouton.

Voir le stylo Modal Popup retardé magnétique par SitePoint ( @SitePoint ) sur CodePen .

Si vous ne voyez pas la fenêtre ouverte, veuillez visiter CodePen et y exécuter la démo.

Syntaxe

Dans la documentation MDN la syntaxe de setTimeout est la suivante:

 var timeoutID = scope.setTimeout (fonction [, delay, arg1, arg2, ...]);
var timeoutID = scope.setTimeout (fonction [, delay]);
var timeoutID = scope.setTimeout (code [, delay]);

où:

  • timeoutID est un ID numérique, qui peut être utilisé en conjonction avec clearTimeout pour annuler la minuterie.
  • scope fait référence à la fenêtre ou l'interface WorkerGlobalScope . La fonction
  • est la fonction à exécuter après l'expiration du temporisateur.
  • le code est une syntaxe alternative qui vous permet d'inclure un chaîne au lieu d'une fonction, qui est compilée et exécutée lorsque le temporisateur expire.
  • retard est le nombre de millisecondes par lequel l'appel de fonction doit être retardé. S'il est omis, cette valeur par défaut est 0.
  • arg1, ..., argN sont des arguments supplémentaires passés à la fonction spécifiée par fonction .

Remarque: les crochets [] indiquent paramètres facultatifs.

setTimeout vs window.setTimeout

Vous remarquerez que la syntaxe ci-dessus utilise scope.setTimeout . Pourquoi?

Eh bien, lors de l'exécution de code dans le navigateur, la portée ferait référence à l'objet global de la fenêtre . setTimeout et window.setTimeout font référence à la même fonction, la seule différence étant que dans la deuxième déclaration, nous référençons la méthode setTimeout comme propriété de la propriété fenêtre objet.

À mon avis, cela ajoute de la complexité pour peu ou pas d'avantages. Si vous avez défini une autre méthode setTimeout qui serait trouvée et renvoyée en priorité dans la chaîne d'étendue, vous avez probablement de plus gros problèmes à vous inquiéter.

Pour les besoins de ce didacticiel, Je vais omettre la fenêtre mais en fin de compte, la syntaxe que vous choisissez dépend de vous.

Exemples d'utilisation

setTimeout accepte une référence à une fonction comme premier argument .

Cela peut être le nom d'une fonction:

 function salutation () {
  alerte ("Salut!");
}
setTimeout (salut, 2000);

Une variable qui fait référence à une fonction (une expression de fonction):

 const salutation = fonction () {
  alerte ("Salut!");
};
setTimeout (salut, 2000);

Ou une fonction anonyme:

 setTimeout (() => {alert ('Howdy!');}, 2000);

Comme indiqué ci-dessus, il est également possible de passer setTimeout une chaîne de code à exécuter:

 setTimeout ('alert ("Howdy!");', 2000);

Cependant, ceci n'est pas conseillé pour les raisons suivantes:

  • Il est difficile à lire (et donc difficile à maintenir et / ou à déboguer).
  • Il utilise un eval implicite qui est un risque potentiel pour la sécurité.
  • Il est plus lent que les alternatives, car il doit invoquer l'interpréteur JS.

Cette question de dépassement de pile offre plus d'informations sur les points ci-dessus.

Passer des paramètres à setTimeout

Dans un scénario de base, la méthode multi-navigateur préférée pour passer des paramètres à un rappel exécuté par setTimeout consiste à utiliser une fonction anonyme comme premier argument.

Dans l'exemple suivant, nous sélectionnons un animal aléatoire dans un tableau animaux et passons cet animal aléatoire comme paramètre à une fonction makeTalk . La fonction makeTalk est ensuite exécutée par setTimeout avec un retard d'une seconde:

 fonction makeTalk (animal) {
  bruits const = {
    chat: 'ronronner',
    chien: 'woof',
    vache: «moo»,
    porc: «oink»,
  }

  console.log (`Un $ {animal} va $ {bruits [animal]}.`);
}

fonction getRandom (arr) {
  retour arr [Math.floor(Math.random()*arr.length)];
}

animaux const = ['cat', 'dog', 'cow', 'pig'];
const randomAnimal = getRandom (animaux);

setTimeout (() => {
  makeTalk (randomAnimal);
}, 1000);

Remarque: J'ai utilisé une fonction régulière ( getRandom ) pour renvoyer un élément aléatoire d'un tableau. Il serait également possible d'écrire ceci comme une expression de fonction en utilisant une fonction flèche:

 const getRandom = arr => arr [Math.floor(Math.random()*arr.length)];

Nous passerons aux fonctions fléchées dans la section suivante.

JS Bin

Une méthode alternative

Comme le montre la syntaxe à la en haut de l'article il existe une deuxième méthode pour passer des paramètres à un rappel exécuté par setTimeout . Cela implique de lister tous les paramètres après le délai.

En référence à notre exemple précédent, cela nous donnerait:

 setTimeout (makeTalk, 1000, randomAnimal);

Malheureusement, cela ne fonctionne pas dans IE9 ou inférieur, où les paramètres apparaissent comme non définis . Si vous n'êtes pas en mesure de devoir prendre en charge IE9, il existe un polyfill disponible sur MDN .

Le problème avec ce

Code exécuté par setTimeout est exécuté dans un contexte d'exécution distinct de la fonction à partir de laquelle il a été appelé. Cela pose problème lorsque le contexte du ce mot-clé est important:

 const dog = {
  son: 'woof',
  écorce () {
    console.log (`Rover dit $ {this.sound}!`);
  }
};

aboiement();
// Sorties: Rover dit woof!

setTimeout (dog.bark, 50);
// Sorties: Rover dit non défini!

La raison de cette sortie est que, dans le premier exemple, ce pointe vers l'objet chien tandis que dans le deuxième exemple ce pointe vers le fenêtre globale objet (qui n'a pas de propriété de son ).

Pour contrer ce problème, il existe différentes mesures…

Définissez explicitement la valeur de this

Vous pouvez le faire en utilisant bind une méthode qui crée une nouvelle fonction qui, lorsqu'elle est appelée, a son this mot-clé défini sur la valeur fournie (dans notre cas, l'objet chien ). Cela nous donnerait:

 setTimeout (dog.bark.bind (dog), 50);

Remarque: bind a été introduit dans ECMAScript 5, donc ne fonctionnera que dans navigateurs plus modernes . Vous pouvez en savoir plus à ce sujet (et sur d'autres méthodes de définition de la valeur de this ) dans cet article SitePoint .

Utiliser une bibliothèque

De nombreuses bibliothèques sont livrées avec une fonction intégrée fonctions pour résoudre ce problème. Par exemple, la méthode jQuery jQuery.proxy () . Cela prend une fonction et retourne une nouvelle qui aura toujours un contexte particulier. Dans notre cas, ce serait:

 setTimeout ($. Proxy (dog.bark, dog), 50);

JS Bin

Utilisation des fonctions fléchées avec setTimeout

Les fonctions fléchées ont été introduites avec ES6. Ils ont une syntaxe beaucoup plus courte qu'une fonction régulière:

 (param1, param2, paramN) => expression

Vous pouvez, bien sûr, les utiliser avec setTimeout mais il y a une chose à savoir – à savoir, que les fonctions fléchées n'ont pas leur cette valeur . Au lieu de cela, ils utilisent la cette valeur du contexte lexical englobant.

En utilisant une fonction régulière:

 const dog = {
  son: 'woof',
  écorce () {
    console.log (`Rover dit $ {this.sound}!`);
  }
};

aboiement();
// Rover dit woof!

Utilisation d'une fonction de flèche:

 const dog = {
  son: 'woof',
  écorce: () => {
    console.log (`Rover dit $ {this.sound}!`);
  }
};

aboiement();
// Rover dit non défini!

Dans le deuxième exemple, ce pointe vers l'objet global de la fenêtre (qui encore une fois, n'a pas de propriété sound ).

This peut nous déclencher lorsque vous utilisez les fonctions fléchées avec setTimeout . Auparavant, nous avons vu comment fournir une fonction appelée dans un setTimeout avec la bonne cette valeur:

 setTimeout (dog.bark.bind (dog), 50);

Cela ne fonctionnera pas lorsque vous utilisez une fonction flèche dans la méthode introduisez car la fonction flèche n'a pas sa propre valeur cette . La méthode enregistrera toujours undefined .

Code de nettoyage avec fonctions fléchées et setTimeout

Cependant, comme les fonctions fléchées n'ont pas leur cette valeur elle peut également fonctionner. à notre avantage.

Considérez un code comme celui-ci:

 const dog = {
  son: 'woof',
  delayBark () {
    setTimeout (
      fonction() {
        console.log (`Rover dit $ {this.sound}!`);
      }
      .bind (this)
    , 1000);
  }
}

dog.delayedBark ();

Il peut être réécrit de façon plus concise avec une fonction flèche:

 const dog = {
  son: 'woof',
  delayBark () {
    setTimeout (
      () => {console.log (`Rover dit $ {this.sound}!`); }, 1000
    );
  }
}

dog.delayedBark ();

Si vous souhaitez une introduction aux fonctions fléchées, veuillez lire « Fonctions flèches ES6: syntaxe grasse et concise en JavaScript ».

Annulation d'une minuterie

Comme nous l'avons appris au début de l'article, la valeur de retour de setTimeout est un ID numérique qui peut être utilisé pour annuler la minuterie en conjonction avec la fonction clearTimeout :

 const timer = setTimeout (myFunction, 3000);
clearTimeout (timer);

Voyons cela en action. Dans le stylet suivant, si vous cliquez sur le bouton Démarrer le compte à rebours un compte à rebours commencera. Si le compte à rebours se termine, les chatons l'obtiennent. Cependant, si vous appuyez sur le bouton Arrêter le compte à rebours le chronomètre sera arrêté et réinitialisé. (Si vous ne voyez pas d'effet cool lorsque le compte à rebours atteint zéro, réexécutez le stylet à l'aide du bouton en bas à droite de l'intégration.)

Voir le stylo SetTimeout Kittens de SitePoint ( @SitePoint ) sur CodePen .

Conclusion

Une mise en garde potentielle à prendre en compte est le fait que setTimeout est asynchrone. Il met en file d'attente la référence de fonction qu'il reçoit pour s'exécuter une fois l'exécution de la pile d'appels en cours terminée. Cependant, il ne s’exécute pas simultanément ou sur un thread séparé (en raison de la nature à thread unique de JavaScript).

 console.log (1);
setTimeout (() => {console.log (2);}, 0);
console.log (3);

// Sorties: 1, 3, 2

Bien que nous appelions setTimeout avec un délai de zéro seconde, les numéros sont toujours déconnectés. En effet, lorsque le minuteur de setTimeout a expiré, le moteur JavaScript place sa fonction de rappel dans une file d'attente, derrière les autres consoles console.log devant être

Si vous souhaitez en savoir plus sur ce qui se passe lorsque JavaScript s'exécute, je recommande vivement cette vidéo de JSConf 2014: Qu'est-ce que c'est que la boucle d'événements de toute façon?

requestAnimationFrame ()

Vous devez également être au courant de requestAnimationFrame . Cette méthode indique au navigateur que vous souhaitez appeler une fonction spécifiée avant le prochain repeint.

Lors de la création d'animations, nous devons privilégier requestAnimationFrame plutôt que d'utiliser setTimeout car cela se déclenchera grossièrement soixante fois par seconde, par opposition à setTimeout qui est appelé après un minimum de n millisecondes. En utilisant requestAnimationFrame nous pouvons éviter de modifier quelque chose deux fois entre deux mises à jour de trame.

Voici un exemple d'utilisation de requestAnimationFrame pour animer un élément div à travers l'élément écran:

 const div = document.querySelector ('# rectangle');
laissez leftPos = 0;

function animateDiv () {
  leftPos + = 1;
  div.style.left = `$ {leftPos} px`;
  if (leftPos <100) requestAnimationFrame (animateDiv);
}

requestAnimationFrame (animateDiv);

Vous pouvez, bien sûr, réaliser la même chose en utilisant setTimeout :

 const div = document.querySelector ('# rectangle');
laissez leftPos = 0;

function animateDiv () {
  leftPos + = 1;
  div.style.left = `$ {leftPos} px`;
  if (leftPos <100) setTimeout (animateDiv, 1000/60);
}

animateDiv ();

Mais comme mentionné, l'utilisation de requestAnimationFrame offre divers avantages, tels que permettre au navigateur d'effectuer des optimisations et d'arrêter des animations dans des onglets inactifs.

Voir le stylo
Animation avec requestAnimationFrame
par SitePoint ( @SitePoint )
sur CodePen .

jQuery.delay ()

Enfin, je voudrais dissiper toute confusion entre l'utilisation du JavaScript natif fonction setTimeout et méthode delay de jQuery .

La méthode delay est spécialement conçue pour ajouter un délai entre les méthodes dans une file d'attente jQuery donnée. Il n'est pas possible d'annuler le retard. Par exemple, si vous souhaitez masquer une image pendant une seconde, la rendre visible pendant cinq secondes, puis la masquer pendant une seconde, vous pouvez procéder comme suit:

 $ ('img') .fadeIn (1000) .delay (5000) .fadeOut (1000);

setTimeout est mieux utilisé pour tout le reste.

Remarque: si vous devez exécuter plusieurs fois le code après un délai spécifié, alors setInterval est plus adapté à la emploi. Vous pouvez lire plus d'informations sur cette fonction ici .

Conclusion

Dans cet article, j'ai montré comment utiliser setTimeout pour retarder l'exécution d'une fonction. J'ai également montré comment passer des paramètres à setTimeout conserver la cette valeur dans son rappel et aussi comment annuler un temporisateur.

Si vous rencontrez un problème de codage concernant le l'utilisation de setTimeout (ou toute autre chose, vraiment), alors veuillez vous rendre sur les forums SitePoint où nous serons heureux de vous aider.




Source link