web-dev-qa-db-fra.com

le délai de setTimeout ne fonctionne pas

J'essaie de faire taire ma tête setTimeout, mais je ne parviens pas à le faire fonctionner correctement.

J'ai mis en place un exemple ici: http://jsfiddle.net/timkl/Fca2n/

Je souhaite que le texte compte à rebours après avoir cliqué sur une ancre - mais ma setTimeout semble se déclencher en même temps, même si j'ai réglé le délai à 1 seconde. 

C'est mon HTML:

<a href="#">Click me!</a>

<span id="target"></span>

C'est mon JS:

$(document).ready(function() {


function foo(){

    writeNumber = $("#target");

    setTimeout(writeNumber.html("1"),1000);
    setTimeout(writeNumber.html("2"),1000);
    setTimeout(writeNumber.html("3"),1000);
    };

$('a').click(function() {
 foo();
});

});

Tout indice sur ce que je pourrais faire de mal est hautement apprécié :)

16
timkl

setTimeout prend une fonction en tant qu'argument. Vous exécutez la fonction et transmettez le résultat à setTimeout (la fonction est donc exécutée immédiatement). Vous pouvez utiliser des fonctions anonymes, par exemple:

setTimeout(function() {
    writeNumber.html("1");
}, 1000);

Notez que la même chose est vraie de setInterval.

42
James Allardice

Vous devez envelopper vos déclarations dans des fonctions anonymes et également décaler vos timings -

setTimeout(function(){writeNumber.html("1")},1000);
setTimeout(function(){writeNumber.html("2")},2000);
setTimeout(function(){writeNumber.html("3")},3000);

Si vous définissez tout sur 1000, les étapes seront exécutées simultanément car la fonction setTimeout exécutera la tâche 1 seconde après l'appel de la fonction, pas 1 seconde après l'appel précédent à la fonction setTimeout.

Démo - http://jsfiddle.net/JSe3H/1/

5
ipr101

Il existe une disposition pour passer des arguments à la fonction. Dans votre cas, vous pouvez le faire en

setTimeout(writeNumber.html,1000,1);
setTimeout(writeNumber.html,1000,2);
setTimeout(writeNumber.html,1000,3);

le troisième argument de la fonction setTimeout sera transmis à la fonction writeNumber.html

2
Achal Saraiya

Vous devez utiliser une fonction reference pour être appelé ultérieurement à l'expiration du délai. Enveloppez chaque instruction dans une fonction anonyme afin qu’elle ne soit pas exécutée immédiatement, mais plutôt à l’expiration du délai.

setTimeout(function() { writeNumber.html("1"); },1000);

En outre, vous souhaitez utiliser une valeur de délai différente pour chacun afin que les minuteries n'expirent pas en même temps. Voir un violon mis à jour à http://jsfiddle.net/RqCqM/

2
tvanfosson

Utilisez simplement setInterval(). Ici c'est ce que j'ai trouvé. Voici votre nouveau javascript:

function foo(){
    writeNumber = $("#target");
    number      = 0;
    writeNumber.html(number);
    setInterval(function(){
        number = number+1;
        writeNumber.html(number);
    },1000);
    };
$('a').click(function() {
 foo();
});
1
Purag

Vous devez utiliser une fonction à appeler une fois le délai écoulé. vous pouvez aussi utiliser une fonction anonyme, alors votre fonction foo ressemblera à ceci:

function foo(){

writeNumber = $("#target");

setTimeout(function() { writeNumber.html("1"); },1000);
setTimeout(function() { writeNumber.html("2"); },1000);
setTimeout(function() { writeNumber.html("3"); },1000);

};
1
Irvin Dominin

J'ai atterri sur cette question. Il a été répondu de manière adéquate et je pense que l’utilisation de setInterval comme suggéré par @Purag est probablement la meilleure approche pour obtenir le comportement fonctionnel souhaité. Cependant, l'exemple de code initial ne tenait pas compte du comportement asynchrone de JavaScript. C'est une erreur fréquente, que j'ai moi-même commise à plus d'une occasion :).

En guise de remarque, je voulais donner une autre solution possible à ce problème, qui imite la tentative initiale, mais cette fois, considérons l'Asynchronousity de Javascript:

setTimeout(function() {
    writeNumber.html("1");
    setTimeout(function() {
        writeNumber.html("1");
        setTimeout(function() {
            writeNumber.html("1");
        }, 1000);
    }, 1000);
}, 1000);

Bien sûr, il s'agit clairement d'un code épouvantable! 

J'en ai donné un travail à JSFiddle dans ma propre question SO . Ce code est un exemple de la soi-disant pyramid of Doom. Et cela peut être atténué en utilisant des promesses JavaScript, comme indiqué dans les réponses à ma question. Il faut un peu de travail pour écrire une version de WriteNumber() qui utilise Promises, mais ensuite le code peut être réécrit en quelque chose comme:

writeNumAsync(0)
    .then(writeNumAsync)
    .then(writeNumAsync)
    .then(writeNumAsync);
0
Bart