Führen Sie das Skript nach einer bestimmten Verzögerung mit JavaScript aus

189

Gibt es eine JavaScript-Methode ähnlich der jQuery delay()oder wait()(um die Ausführung eines Skripts um einen bestimmten Zeitraum zu verzögern)?

Niyaz
quelle

Antworten:

189

Es gibt Folgendes:

setTimeout(function, milliseconds);

Funktion, die nach der Zeit übergeben werden kann, nach der die Funktion ausgeführt wird.

Siehe: Fenster setTimeout()Methode .

Abhinav
quelle
3
Es ist kein Ausdruck, der ausgeführt wird, sondern eine Funktion. Die Antwort von @Marius veranschaulicht dies.
Pedrofurla
117
Dies ist keine Verzögerung, es ist eine Gabelung. Die Verzögerung sollte im selben Thread funktionieren.
DragonLord
13
Dadurch wird function_reference sofort ausgeführt. Um "zu arbeiten" (asynchron), sollte Folgendes angegeben werden: setTimeout (function () {MethodToCall ();}, 1000);
Bernoulli IT
6
Ich möchte darauf hinweisen, dass es sich um JavaScript handelt. Das Aufrufen von "Threads" oder dass es "synchron" funktionieren sollte, mag technisch und semantisch zutreffen, passt aber nicht wirklich in den Kontext von JavaScript, da es mit keiner dieser Methoden wirklich eine Möglichkeit gibt, eine Verzögerung zu erreichen (Sie tun es nicht) t "Threads" in JS erstellen, wie Sie es in anderen Sprachen tun). Dies wird auch nicht sofort ausgeführt, es function_referencesei denn, Sie schließen ein (). Dh function_referenceist genau das - eine Referenz; Das Übergeben function_reference()würde die Funktion sofort aufrufen.
Danny Bullis
237

Nur um das zu ergänzen, was alle anderen gesagt haben setTimeout: Wenn Sie in Zukunft eine Funktion mit einem Parameter aufrufen möchten, müssen Sie einige anonyme Funktionsaufrufe einrichten.

Sie müssen die Funktion als Argument übergeben, damit sie später aufgerufen werden kann. In der Tat bedeutet dies ohne Klammern hinter dem Namen. Im Folgenden wird die Warnung sofort aufgerufen und "Hallo Welt" angezeigt:

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

Um dies zu beheben, können Sie entweder den Namen einer Funktion eingeben (wie es Flubba getan hat) oder eine anonyme Funktion verwenden. Wenn Sie einen Parameter übergeben müssen, müssen Sie eine anonyme Funktion verwenden.

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

Wenn Sie diesen Code ausführen, werden Sie feststellen, dass das Popup nach 2 Sekunden "Hallo Stapelüberlauf" anzeigt. Dies liegt daran, dass sich der Wert der Variablen a in diesen zwei Sekunden geändert hat. Damit nach zwei Sekunden "Hallo Welt" angezeigt wird, müssen Sie den folgenden Codeausschnitt verwenden:

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

Es wird 2 Sekunden warten und dann 'Hallo Welt' erscheinen.

Marius
quelle
37

Nur um ein wenig zu erweitern ... Sie können Code direkt im setTimeoutAufruf ausführen , aber wie @patrick sagt, weisen Sie normalerweise eine Rückruffunktion wie diese zu. Die Zeit ist Millisekunden

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

Wenn Sie wirklich eine blockierende (synchrone) delayFunktion haben möchten (für was auch immer), warum nicht so etwas tun:

<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
quelle
2
Die Schwierigkeit bei dieser Lösung besteht darin, dass ein Prozessor aktiv verwendet wird, was zu einem erhöhten Stromverbrauch und einer Verringerung der für andere Threads / Prozesse verfügbaren Ressourcen (z. B. andere Registerkarten, andere Programme) führt. Im Gegensatz dazu wird im Ruhezustand die Verwendung von Systemressourcen durch einen Thread vorübergehend ausgesetzt.
Ramcdougal
1
Verwenden Sie besser Date.now () anstelle von new Date () und denken Sie nicht an Speicherlecks
WayFarer
1
Natürlich ist es CPU-intensiv, aber für schnelle und schmutzige Tests funktioniert es
Maris B.
Ich möchte eine Version davon, die den Thread nicht sperrt, damit ich das DOM vor dem Ing delayaktualisieren kann (um diese Frage zu beantworten ). Gibt es eine Möglichkeit dazu?
Gui Imamura
3
Eine kompaktere Routine: Funktionsverzögerung (ms) {var start_time = Date.now (); while (Date.now () - start_time <ms); }
Duke
15

Sie müssen setTimeout verwenden und ihm eine Rückruffunktion übergeben. Der Grund, warum Sie Sleep in Javascript nicht verwenden können, ist, dass Sie die gesamte Seite in der Zwischenzeit daran hindern würden, etwas zu tun. Kein guter Plan. Verwenden Sie das Ereignismodell von Javascript und bleiben Sie glücklich. Kämpfe nicht dagegen an!

Patrick
quelle
2
Trotzdem wäre es zu Testzwecken nützlich. B. das Verzögern einer Formularübermittlung um einige Sekunden, um Seitenänderungen auszuwerten, bevor eine neue HTTP-Anforderung gestellt wird.
Rushinge
1
@rushinge dann setzen Sie den Rückruf, um das Formular zu senden und deaktivieren Sie das Standardformular senden
Populus
1
Schlechte Idee, einen Link als Code zu hinterlassen ... da es jetzt nicht funktioniert.
Emmet Arries
1
Oder weißt du, ich könnte es einfach reparieren.
Patrick
14

Sie können auch window.setInterval () verwenden , um in regelmäßigen Abständen wiederholt Code auszuführen.

rcoup
quelle
2
setInterval () sollte nicht verwendet werden, sondern sollte setTimeout
paul
9
setTimeout()macht es einmal, setInterval()macht es wiederholt. Wenn Sie möchten, dass Ihr Code alle 5 Sekunden ausgeführt wird, setInterval()ist dies für den Job vorgesehen.
Gruppe
11

Um die früheren Kommentare zu ergänzen, möchte ich Folgendes sagen:

Die setTimeout()Funktion in JavaScript unterbricht die Ausführung des Skripts nicht per se, sondern weist den Compiler lediglich an, den Code irgendwann in der Zukunft auszuführen.

Es gibt keine Funktion, die die in JavaScript integrierte Ausführung anhalten kann. Sie können jedoch Ihre eigene Funktion schreiben, die so etwas wie eine bedingungslose Schleife ausführt, bis die Zeit erreicht ist, indem Sie die Date()Funktion verwenden und das benötigte Zeitintervall hinzufügen.

narasi
quelle
11

Wenn Sie nur eine Verzögerung testen müssen, können Sie Folgendes verwenden:

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

Und wenn Sie dann um 2 Sekunden verzögern möchten, tun Sie Folgendes:

delay(2000);

Könnte aber nicht das Beste für die Produktion sein. Mehr dazu in den Kommentaren

Christoffer
quelle
@ U2744 SNOWFLAKE Können Sie versuchen, in Ihrem Kommentar etwas präziser zu sein
Christoffer
1
Nun, es ist eine Besetztschleife, die die Batterien von Laptops und anderen Mobilgeräten entlädt und wahrscheinlich auch verhindert, dass die Benutzeroberfläche reagiert (oder sogar anzeigt).
Ry-
@ U2744SNOWFLAKE Sinnvoll. Habe die Antwort aktualisiert, wofür ich diese Funktion benutzt habe :)
Christoffer
2
Funktioniert gut genug in der Entwicklung für eine schnelle und schmutzige (und vorübergehende) Lösung.
HumanInDisguise
5

Warum kannst du den Code nicht hinter ein Versprechen setzen? (tippte oben auf meinem Kopf ein)

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

Al Joslin
quelle
5

Die einfache Antwort lautet:

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

Die obige Funktion wartet 1 Sekunde (1000 ms) und setzt dann x auf 1. Offensichtlich ist dies ein Beispiel; Innerhalb der anonymen Funktion können Sie alles tun, was Sie wollen.

Luca
quelle
4

Die Erklärung von Maurius (höchste positive Antwort) mit den drei verschiedenen Anrufmethoden hat mir sehr gut gefallen setTimeout .

In meinem Code möchte ich nach Abschluss eines AJAX-Speicherereignisses automatisch zur vorherigen Seite navigieren. Der Abschluss des Speicherereignisses enthält eine leichte Animation im CSS, die angibt, dass das Speichern erfolgreich war.

In meinem Code habe ich einen Unterschied zwischen den ersten beiden Beispielen gefunden:

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

Dieser wartet nicht auf das Timeout - das back () wird fast sofort aufgerufen, egal welche Nummer ich für die Verzögerung eingegeben habe.

Ändern Sie dies jedoch in:

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

Das macht genau das, was ich mir erhofft hatte.

Dies ist nicht spezifisch für die back () -Operation, dasselbe passiert mit alert(). Grundsätzlich wird bei der alert()im ersten Fall verwendeten die Verzögerungszeit ignoriert. Wenn ich das Popup schließe, wird die Animation für das CSS fortgesetzt.

Daher würde ich die zweite oder dritte Methode empfehlen, die er beschreibt, auch wenn Sie integrierte Funktionen verwenden und keine Argumente verwenden.

Doug
quelle
1

Ich hatte einige Ajax-Befehle, die ich mit einer Verzögerung dazwischen ausführen wollte. Hier ist ein einfaches Beispiel für einen Weg, dies zu tun. Ich bin bereit, für meinen unkonventionellen Ansatz in Stücke gerissen zu werden. :) :)

//  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());

Sie können den Codeblock kopieren und in ein Konsolenfenster einfügen und Folgendes sehen:

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
quelle
1

Die einfachste Lösung, um Ihre Funktion mit Verzögerung aufzurufen, ist:

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

Verzögerungsfunktion:

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

Verwendung innerhalb der asyncFunktion:

await delay(1000);
Zuhair Taha
quelle
-1

Wie bereits erwähnt, ist setTimeout Ihre sicherste Wahl.
Manchmal können Sie die Logik jedoch nicht von einer neuen Funktion trennen. Dann können Sie Date.now () verwenden, um Millisekunden abzurufen und die Verzögerung selbst durchzuführen.

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
quelle