web-dev-qa-db-ger.com

setTimeout Verzögerung funktioniert nicht

Ich versuche, meinen Kopf um setTimeout zu wickeln, aber ich kann nicht, dass es richtig funktioniert.

Ich habe hier ein Beispiel eingerichtet: http://jsfiddle.net/timkl/Fca2n/

Ich möchte, dass ein Text Countdown läuft, nachdem ein Anker angeklickt wurde - meine setTimeout scheint jedoch gleichzeitig zu schießen, obwohl ich die Verzögerung auf 1 Sek. 

Das ist mein HTML:

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

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

Das ist meine 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();
});

});

Jeder Hinweis, was ich falsch machen könnte, wird sehr geschätzt :)

16
timkl

setTimeout nimmt eine Funktion als Argument an. Sie führen die Funktion aus und übergeben das Ergebnis an setTimeout (damit die Funktion sofort ausgeführt wird). Sie können anonyme Funktionen verwenden, zum Beispiel:

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

Beachten Sie, dass dies auch für setInterval gilt.

42
James Allardice

Sie müssen Ihre Aussagen in anonyme Funktionen einschließen und auch Ihre Timings gestaffelt machen -

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

Wenn Sie alles auf 1000 setzen, werden die Schritte ziemlich gleichzeitig ausgeführt, da die Funktion setTimeout die Task 1 Sekunde nach dem Aufruf der Funktion ausführt, nicht 1 Sekunde, nachdem der vorherige Aufruf der Funktion setTimeout beendet wurde.

Demo - http://jsfiddle.net/JSe3H/1/

5
ipr101

Es gibt eine Bestimmung, um Argumente an die Funktion zu übergeben. In Ihrem Fall können Sie es tun

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

das dritte Argument der Funktion setTimeout wird an die Funktion writeNumber.html übergeben

2
Achal Saraiya

Sie müssen eine Funktion reference verwenden, die später aufgerufen wird, wenn der Timer abläuft. Binden Sie jede Anweisung in eine anonyme Funktion ein, sodass sie nicht sofort ausgeführt wird, sondern wenn der Timer abläuft.

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

Außerdem möchten Sie für jeden einen anderen Verzögerungswert verwenden, damit die Timer nicht gleichzeitig ablaufen. Eine aktualisierte Geige finden Sie unter http://jsfiddle.net/RqCqM/

2
tvanfosson

Verwenden Sie einfach setInterval(). Hier was ich mir ausgedacht habe. Hier ist dein neues 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

Sie müssen eine Funktion verwenden, die nach Ablauf des Timeouts aufgerufen wird. Sie können auch eine anonyme Funktion verwenden, dann sieht Ihre Funktion foo so aus:

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

Ich bin auf diese Frage gelandet. Es wurde ausreichend beantwortet, und ich denke, die Verwendung von setInterval als vorgeschlagenen @Purag ist wahrscheinlich der beste Ansatz, um das gewünschte Funktionsverhalten zu erhalten. Das ursprüngliche Codebeispiel berücksichtigte jedoch nicht das asynchrone Verhalten von JavaScript. Dies ist ein häufig auftretender Fehler, den ich mir öfters gemacht habe :).

Als Randnotiz wollte ich eine andere mögliche Lösung dafür geben, die den ersten Versuch nachahmt, aber diesmal betrachten wir die Asynchronität von Javascript:

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

Nun, natürlich ist das eindeutig ein schrecklicher Code! 

Ich habe eine funktionierende JSFiddle davon in meiner eigenen SO Frage gegeben. Dieser Code veranschaulicht die sogenannte Pyramide von Doom. Dies kann durch die Verwendung von JavaScript-Versprechen gemindert werden, wie in den Antworten auf meine Frage gezeigt. Es ist etwas Arbeit nötig, um eine Version von WriteNumber() zu schreiben, die Promises verwendet. Dann kann der Code jedoch folgendermaßen umgeschrieben werden:

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