Exécuter le script après un délai spécifique à l'aide de JavaScript

192

Existe-t-il une méthode JavaScript similaire à jQuery delay()ou wait()(pour retarder l'exécution d'un script pendant une durée spécifique)?

Niyaz
la source

Réponses:

190

Il y a ce qui suit:

setTimeout(function, milliseconds);

fonction qui peut être passée le temps après lequel la fonction sera exécutée.

Voir: Méthode de la fenêtresetTimeout() .

Abhinav
la source
3
Ce n'est pas une expression qui est exécutée, c'est une fonction. La réponse de @Marius illustre cela.
pedrofurla
117
ce n'est pas un retard, c'est une fourchette. Le délai devrait fonctionner dans le même fil.
DragonLord
14
Cela exécutera immédiatement function_reference. Pour "travailler" (de manière asynchrone), il doit être indiqué comme suit: setTimeout (function () {MethodToCall ();}, 1000);
Bernoulli IT
6
Je tiens à souligner que nous parlons de JavaScript; amener des "threads" ou que cela devrait fonctionner "de manière synchrone" peut être vrai techniquement et sémantiquement mais ne rentre pas vraiment dans le contexte de JavaScript, étant donné qu'il n'y a vraiment aucun moyen d'obtenir un retard avec l'une ou l'autre de ces méthodes (vous ne t créer des "threads" dans JS comme vous le faites dans d'autres langues). De plus, cela ne s'exécutera pas immédiatement à function_referencemoins que vous n'incluiez (). Ie function_referenceest juste cela - une référence; passer function_reference()invoquerait la fonction immédiatement.
Danny Bullis
240

Juste pour ajouter à ce que tout le monde a dit à propos de setTimeout: si vous souhaitez appeler une fonction avec un paramètre à l'avenir, vous devez configurer des appels de fonction anonymes.

Vous devez passer la fonction en tant qu'argument pour qu'elle soit appelée ultérieurement. En effet, cela signifie sans crochets derrière le nom. Ce qui suit appellera l'alerte immédiatement et affichera `` Bonjour tout le monde '':

var a = "world";
setTimeout(alert("Hello " + a), 2000);

Pour résoudre ce problème, vous pouvez soit mettre le nom d'une fonction (comme Flubba l'a fait), soit utiliser une fonction anonyme. Si vous avez besoin de passer un paramètre, vous devez utiliser une fonction anonyme.

var a = "world";
setTimeout(function(){alert("Hello " + a)}, 2000);
a = "Stack Overflow";

Mais si vous exécutez ce code, vous remarquerez qu'au bout de 2 secondes, la fenêtre contextuelle indiquera «Hello Stack Overflow». En effet, la valeur de la variable a a changé au cours de ces deux secondes. Pour qu'il dise «Bonjour tout le monde» après deux secondes, vous devez utiliser l'extrait de code suivant:

function callback(a){
    return function(){
        alert("Hello " + a);
    }
}
var a = "world";
setTimeout(callback(a), 2000);
a = "Stack Overflow";

Il attendra 2 secondes, puis affichera «Hello world».

Marius
la source
38

Juste pour développer un peu ... Vous pouvez exécuter du code directement dans l' setTimeoutappel, mais comme @patrick le dit, vous attribuez normalement une fonction de rappel, comme celle-ci. Le temps est en millisecondes

setTimeout(func, 4000);
function func() {
    alert('Do stuff here');
}
Polsonby
la source
27

Si vous voulez vraiment avoir une fonction de blocage (synchrone) delay(pour quelque chose), pourquoi ne pas faire quelque chose comme ceci:

<script type="text/javascript">
    function delay(ms) {
        var cur_d = new Date();
        var cur_ticks = cur_d.getTime();
        var ms_passed = 0;
        while(ms_passed < ms) {
            var d = new Date();  // Possible memory leak?
            var ticks = d.getTime();
            ms_passed = ticks - cur_ticks;
            // d = null;  // Prevent memory leak?
        }
    }

    alert("2 sec delay")
    delay(2000);
    alert("done ... 500 ms delay")
    delay(500);
    alert("done");
</script>
Mario Werner
la source
2
La difficulté avec cette solution est qu'elle utilise activement un processeur, ce qui conduit à une consommation d'énergie accrue et à une diminution des ressources disponibles pour d'autres threads / processus (par exemple, d'autres onglets, d'autres programmes). Sleep, en revanche, suspend temporairement l'utilisation des ressources système par un thread.
ramcdougal
1
mieux utiliser Date.now () au lieu de new Date () et ne pas penser aux fuites de mémoire
WayFarer
1
Bien sûr, il est gourmand en CPU, mais pour des tests rapides et sales, cela fonctionne
Maris B.
3
Une routine plus compacte: function delay (ms) {var start_time = Date.now (); while (Date.now () - heure_début <ms); }
Duke
;(function(){function a(b,a){!0!==a&&(b*=1E3);for(var c=Date.now();Date.now()-c<b;);}window.hasOwnProperty("delay")||(window.delay=a)})();Utilisez secondes ou msec. Exemple avec 3 secondes: delay(3);Exemple avec 500 millisecondes:delay(500, true);
SpYk3HH
15

Vous devez utiliser setTimeout et lui passer une fonction de rappel. La raison pour laquelle vous ne pouvez pas utiliser sleep en javascript est que vous empêchez toute la page de faire quoi que ce soit entre-temps. Pas un bon plan. Utilisez le modèle d'événement de Javascript et restez heureux. Ne vous battez pas!

Patrick
la source
2
Cela serait néanmoins utile à des fins de test. Comme retarder la soumission d'un formulaire de quelques secondes pour évaluer les changements de page avant qu'une nouvelle requête HTTP ne soit effectuée.
rushinge
1
@rushinge puis définissez le rappel pour soumettre le formulaire et désactiver la soumission de formulaire par défaut
Populus
14

Vous pouvez également utiliser window.setInterval () pour exécuter du code à plusieurs reprises à intervalles réguliers.

rcoup
la source
2
setInterval () ne devrait pas être utilisé à la place devrait utiliser setTimeout
paul
9
setTimeout()le fait une fois, le setInterval()fait à plusieurs reprises. Si vous voulez que votre code s'exécute toutes les 5 secondes, il setInterval()est fait pour le travail.
rcoup
11

Pour ajouter aux commentaires précédents, je voudrais dire ce qui suit:

le setTimeout() fonction en JavaScript ne suspend pas l'exécution du script en soi, mais indique simplement au compilateur d'exécuter le code ultérieurement.

Il n'y a pas de fonction qui puisse réellement suspendre l'exécution intégrée à JavaScript. Cependant, vous pouvez écrire votre propre fonction qui fait quelque chose comme une boucle inconditionnelle jusqu'à ce que le temps soit atteint en utilisant la Date()fonction et en ajoutant l'intervalle de temps dont vous avez besoin.

Narasi
la source
11

Si vous avez seulement besoin de tester un délai, vous pouvez utiliser ceci:

function delay(ms) {
   ms += new Date().getTime();
   while (new Date() < ms){}
}

Et puis si vous voulez retarder de 2 secondes vous faites:

delay(2000);

Ce n'est peut-être pas le meilleur pour la production. Plus à ce sujet dans les commentaires

Christoffer
la source
1
Eh bien, c'est une boucle occupée qui épuisera les batteries des ordinateurs portables et autres appareils mobiles, et empêchera probablement également l'interface utilisateur de répondre (ou même de s'afficher).
Ry-
@ U2744SNOWFLAKE Cela a du sens. J'ai mis à jour la réponse, pour ce que j'ai utilisé cette fonction pour :)
Christoffer
2
Fonctionne assez bien en développement pour une solution rapide et sale (et temporaire).
HumanInDisguise
6

pourquoi ne pouvez-vous pas mettre le code derrière une promesse? (tapé du haut de ma tête)

new Promise(function(resolve, reject) {
  setTimeout(resolve, 2000);
}).then(function() {
  console.log('do whatever you wanted to hold off on');
});

Al Joslin
la source
5

La réponse simple est:

setTimeout(
    function () {
        x = 1;
    }, 1000);

La fonction ci-dessus attend 1 seconde (1000 ms) puis met x à 1. Evidemment, ceci est un exemple; vous pouvez faire tout ce que vous voulez dans la fonction anonyme.

Luca
la source
4

J'ai vraiment aimé l'explication de Maurius (la réponse la plus élevée) avec les trois méthodes différentes pour appeler setTimeout.

Dans mon code, je souhaite accéder automatiquement à la page précédente à la fin d'un événement de sauvegarde AJAX. La fin de l'événement de sauvegarde a une légère animation dans le CSS indiquant que la sauvegarde a réussi.

Dans mon code, j'ai trouvé une différence entre les deux premiers exemples:

setTimeout(window.history.back(), 3000);

Celui-ci n'attend pas le délai d'attente - le back () est appelé presque immédiatement, quel que soit le nombre que j'ai mis pour le délai.

Cependant, remplacez-le par:

setTimeout(function() {window.history.back()}, 3000);

Cela fait exactement ce que j'espérais.

Ce n'est pas spécifique à l'opération back (), il en va de même avec alert(). Fondamentalement, avec le alert()utilisé dans le premier cas, le temps de retard est ignoré. Lorsque je ferme la fenêtre contextuelle, l'animation du CSS continue.

Ainsi, je recommanderais la deuxième ou la troisième méthode qu'il décrit même si vous utilisez des fonctions intégrées et n'utilisez pas d'arguments.

Doug
la source
1

J'avais des commandes ajax que je voulais exécuter avec un délai entre les deux. Voici un exemple simple d'une façon de faire cela. Je suis prêt à être déchiré en lambeaux pour mon approche non conventionnelle. :)

//  Show current seconds and milliseconds
//  (I know there are other ways, I was aiming for minimal code
//  and fixed width.)
function secs()
{
    var s = Date.now() + ""; s = s.substr(s.length - 5);
  return s.substr(0, 2) + "." + s.substr(2);
}

//  Log we're loading
console.log("Loading: " + secs());

//  Create a list of commands to execute
var cmds = 
[
    function() { console.log("A: " + secs()); },
    function() { console.log("B: " + secs()); },
    function() { console.log("C: " + secs()); },
    function() { console.log("D: " + secs()); },
    function() { console.log("E: " + secs()); },
  function() { console.log("done: " + secs()); }
];

//  Run each command with a second delay in between
var ms = 1000;
cmds.forEach(function(cmd, i)
{
    setTimeout(cmd, ms * i);
});

// Log we've loaded (probably logged before first command)
console.log("Loaded: " + secs());

Vous pouvez copier le bloc de code et le coller dans une fenêtre de console et voir quelque chose comme:

Loading: 03.077
Loaded: 03.078
A: 03.079
B: 04.075
C: 05.075
D: 06.075
E: 07.076
done: 08.076
JohnnyIV
la source
1

La solution la plus simple pour appeler votre fonction avec délai est:

function executeWithDelay(anotherFunction) {
    setTimeout(anotherFunction, delayInMilliseconds);
}
Jackkobec
la source
0

fonction de retard:

/**
 * delay or pause for some time
 * @param {number} t - time (ms)
 * @return {Promise<*>}
 */
const delay = async t => new Promise(resolve => setTimeout(resolve, t));

utilisation à l'intérieur de la asyncfonction:

await delay(1000);
Zuhair Taha
la source
-1

Comme d'autres l'ont dit, setTimeout est votre pari le plus sûr,
mais parfois vous ne pouvez pas séparer la logique d'une nouvelle fonction, vous pouvez utiliser Date.now () pour obtenir des millisecondes et faire le retard vous-même ...

function delay(milisecondDelay) {
   milisecondDelay += Date.now();
   while(Date.now() < milisecondDelay){}
}

alert('Ill be back in 5 sec after you click OK....');
delay(5000);
alert('# Im back # date:' +new Date());

JavaSheriff
la source