Sleep in JavaScript - Verzögerung zwischen Aktionen

128

Gibt es eine Möglichkeit, in JavaScript zu schlafen, bevor eine weitere Aktion ausgeführt wird?

Beispiel:

 var a = 1+3;
 // Sleep 3 seconds before the next action here
 var b = a + 4;
Jin Yong
quelle

Antworten:

139

Sie können verwenden setTimeout, um einen ähnlichen Effekt zu erzielen:

var a = 1 + 3;
var b;
setTimeout(function() {
    b = a + 4;
}, (3 * 1000));

Dies "schläft" JavaScript nicht wirklich - es führt nur die Funktion aus, die setTimeoutnach einer bestimmten Dauer (angegeben in Millisekunden) übergeben wird. Obwohl es möglich ist, eine Schlaffunktion für JavaScript zu schreiben, ist es am besten, setTimeoutwenn möglich , diese zu verwenden , da sie während der Ruhephase nicht alles einfriert.

Steve Harrison
quelle
9
Schauen Sie sich auch setInterval () an. Es ähnelt setTimeout (), aber Ihre Funktion wird mehrmals aufgerufen (bis Sie sie stoppen). Dies ist nützlich, wenn Sie im Schlaf etwas tun möchten (z. B. Fortschrittsaktualisierungen durchführen, einen internen Status beibehalten oder was auch immer).
Anders Sandvig
5
Dies beantwortet die Frage nicht. Die Frage fragt nach einem "Schlaf" -Äquivalent, das dies nicht ist.
Felwithe
Diese Antwort stimmt zwar nicht mit der gestellten Frage überein, ist aber nützlicher als die Schleife und vergleicht Date.now (). Niemand, was eine blockierte Schleife verwendet, um das Gerät zu schlafen.
Li Chunlin
2
Es sei denn natürlich, eine Sperrschleife ist genau das , was jemand will.
Wonko der Gesunde
54

Für den Fall, dass Sie wirklich nur brauchen sleep(), um etwas zu testen. Beachten Sie jedoch, dass der Browser beim Debuggen meistens abstürzt - wahrscheinlich benötigen Sie ihn deshalb trotzdem. Im Produktionsmodus werde ich diese Funktion auskommentieren.

function pauseBrowser(millis) {
    var date = Date.now();
    var curDate = null;
    do {
        curDate = Date.now();
    } while (curDate-date < millis);
}

Nicht benutzen new Date() in der Schleife verwenden, es sei denn, Sie möchten Speicher, Rechenleistung, Akku und möglicherweise die Lebensdauer Ihres Geräts verschwenden.

Rodrigo
quelle
8
Diese Antwort verdient mehr Stimmen. Darsteller der Frage nur wegen dieser Antwort.
Jagc
Was ist mit der Warnung "zu viel Rekursion"?
Oki Erie Rinaldi
1
@OkiErieRinaldi Es gibt dort keine Rekursion, es ist nur eine Schleife.
Rodrigo
7
@ 3.1415926535897932384626433833 Nun, jemand hat nach einer "Schlaf" -Funktion gefragt, das ist was hier ist. Ich habe es einmal benutzt, kann mich nicht genau erinnern, für welche Art von Debugging. Wenn ich es jemals wieder brauche, weiß ich genau, wo ich es finden kann. Wenn Sie eine andere Funktion bevorzugen, haben Sie die Wahl. Ist es nicht toll, wählen zu können?
Rodrigo
2
"Beschäftigt warten".
Zeek2
12

ECMAScript 6-Version mit Generatoren mit Ausbeute für "Codeblocking":

Da die ursprüngliche Frage vor sieben Jahren gestellt wurde, habe ich mich nicht darum gekümmert, mit dem genauen Code zu antworten, da dies einfach zu einfach und bereits beantwortet ist. Dies sollte bei komplizierteren Problemen helfen, z. B. wenn Sie mindestens zwei Schlafphasen benötigen oder wenn Sie planen, die asynchrone Ausführung zu sequenzieren. Sie können es jederzeit an Ihre Bedürfnisse anpassen.

let sleeptime = 100
function* clock()
{
    let i = 0
    while( i <= 10000 )
    {
        i++
        console.log(i); // actually, just do stuff you wanna do.
        setTimeout(
            ()=>
            {
                clk.next()
            }
            , sleeptime
        )
        yield
    }
}

let clk = clock()
clk.next()

Funktion*

() => Pfeilfunktion

Sie können Ereignisse auch über Versprechen verketten :

function sleep(ms)
{
    return(
        new Promise(function(resolve, reject)
        {
            setTimeout(function() { resolve(); }, ms);
        })
    );
}


sleep(1000).then(function()
{
    console.log('1')
    sleep(1000).then(function()
    {
        console.log('2')
    })
})

Oder viel einfacher und weniger ausgefallen wäre

function sleep(ms, f)
{
    return(
        setTimeout(f, ms)
    )
}


sleep(500, function()
{
    console.log('1')
    sleep(500, function()
    {
        console.log('2')
    })
})
console.log('Event chain launched')

Wenn Sie nur darauf warten, dass eine Bedingung eintritt, können Sie so warten

function waitTill(condition, thenDo)
{
    if (eval(condition))
    {
        thenDo()
        return
    }

    setTimeout(
        ()    =>
        {
            waitTill(condition, thenDo)
        }
        ,
        1
    )
}

x=0

waitTill(
    'x>2 || x==1'
    ,
    ()    =>
    {
        console.log("Conditions met!")
    }
)

// Simulating the change
setTimeout(
    () =>
    {
        x = 1
    }
    ,
    1000
)

Mhor Mé
quelle
11

Update 2018

Die neuesten Versionen von Safari, Firefox und Node.j unterstützen jetzt auch asynchrone / warten / versprechen.

Verwenden von async / await / Promises:

(Ab 1/2017, unterstützt von Chrome, jedoch nicht von Safari, Internet Explorer, Firefox, Node.js)

'use strict';

function sleep(ms) {
  return new Promise(res => setTimeout(res, ms));
}

let myAsyncFunc = async function() {
  console.log('Sleeping');
  await sleep(3000);
  console.log('Done');
}

myAsyncFunc();

Update 2017

JavaScript hat sich weiterentwickelt, seit diese Frage gestellt wurde, und verfügt nun über Generatorfunktionen. Das neue Programm async / await / Promise wird eingeführt. Im Folgenden finden Sie zwei Lösungen, eine mit Generatorfunktion, die auf allen modernen Browsern funktioniert, und eine andere mit dem neuen Async / Warten, das noch nicht überall unterstützt wird.

Verwenden einer Generatorfunktion:

'use strict';

let myAsync = (g) => (...args) => {
    let f, res = () => f.next(),
        sleep = (ms) => setTimeout(res, ms);
    f = g.apply({sleep}, args); f.next();
};

let myAsyncFunc = myAsync(function*() {
    let {sleep} = this;
    console.log("Sleeping");
    yield sleep(3000);
    console.log("Done");
});

myAsyncFunc();

Beachten Sie, dass beide Lösungen asynchroner Natur sind. Dies bedeutet, dass myAsyncFunc (in beiden Fällen) im Schlaf zurückkehrt.

Es ist wichtig zu beachten, dass sich diese Frage von der JavaScript-Version von sleep () unterscheidet. wo der Anforderer eher nach echtem Schlaf fragt (keine andere Codeausführung im Prozess) als nach einer Verzögerung zwischen den Aktionen.

niry
quelle
1
Beste Antwort bisher !! Ich habe 30 Minuten damit verbracht, überall zu suchen, um das zu finden. Vielen Dank !!!
538ROMEO
1
Ich habe diese Antwort verpasst, als ich nach einer Lösung gesucht und das Fahrrad neu erfunden habe: D Wenn ich es nur sehen würde, bevor es mir Stunden sparen würde !! Upvoted!
sserzant
let co = gen => (...args) => { let iter = gen(...args); let resume = () => new Promise((resolve, reject) => { let result = iter.next(); if (result.done) resolve(result.value); else Promise.resolve(result.value).then(resume).then(resolve, reject); }); return resume(); };Sie let asyncAdd = co(function* (a, b) { console.log('Sleeping'); yield sleep(3000); console.log('Done'); return a + b; }); asyncAdd(3, 4).then(console.log);können die Definition von sleep()aus Ihrem zweiten Codeblock verwenden.
Patrick Roberts
3

Wenn Sie weniger klobige Funktionen als setTimeoutund möchten setInterval, können Sie sie in Funktionen einschließen, die nur die Reihenfolge der Argumente umkehren und ihnen nette Namen geben:

function after(ms, fn){ setTimeout(fn, ms); }
function every(ms, fn){ setInterval(fn, ms); }

CoffeeScript-Versionen:

after = (ms, fn)-> setTimeout fn, ms
every = (ms, fn)-> setInterval fn, ms

Sie können sie dann gut mit anonymen Funktionen verwenden:

after(1000, function(){
    console.log("it's been a second");
    after(1000, function(){
        console.log("it's been another second");
    });
});

Jetzt liest es sich leicht als "nach N Millisekunden, ..." (oder "alle N Millisekunden, ...")

1j01
quelle
2

Eine andere Möglichkeit besteht darin, Promise und setTimeout zu verwenden (beachten Sie, dass Sie sich in einer Funktion befinden und diese mit dem Schlüsselwort async als asynchron festlegen müssen):

async yourAsynchronousFunction () {

    var a = 1+3;

    await new Promise( (resolve) => {
        setTimeout( () => { resolve(); }, 3000);
    }

    var b = a + 4;

}
Ostn
quelle
2

Hier ist eine sehr einfache Möglichkeit, die sich wie ein synchroner Schlaf / eine synchrone Pause anfühlt, aber legitimer asynchroner Code ist.

// Create a simple pause function
const pause = (timeoutMsec) => new Promise(resolve => setTimeout(resolve,timeoutMsec))

async function main () {
    console.log('starting');
    // Call with await to pause.  Note that the main function is declared asyc
    await pause(3*1000)
    console.log('done');
}

user2330237
quelle
1

Sie können einfaches Javascript verwenden. Dies ruft Ihre Funktion / Methode nach 5 Sekunden auf:

setTimeout(()=> { your_function(); }, 5000);
Das schwarze Pferd
quelle
0

Es gibt verschiedene Möglichkeiten, um dieses Problem zu lösen. Wenn wir die setTimeoutFunktion verwenden, lernen wir sie zuerst kennen. Diese Funktion hat drei Parameter: functionoder code, delay(in Millisekunden) und die parameters. Da die Funktion oder Code - Parameter erforderlich ist, sind die anderen. Sobald Sie die Verzögerung nicht eingegeben haben , wird sie auf Null gesetzt.

Weitere Details setTimeout() dazu finden Sie unter diesem Link .

Vereinfachte Version:

var a = 1 + 3;
var b;
console.log('a = ' + a);
setTimeout(function(){ 
    b = a + 4; 
    console.log('b = ' + b);
}, 1000);

Ausgabe:
a = 4
24 -> Nummernkennung der Liste der aktiven Zeitüberschreitungen
b = 8


Verwenden des Parameterpasses:

var a = 1 + 3;
var b;
console.log('a = ' + a);
setTimeout(myFunction, 1000, a);

function myFunction(a)
{
    var b = a + 4;
    console.log('b = ' + b);
}

Ausgabe:
a = 4
25 -> Nummernkennung der Liste der aktiven Zeitüberschreitungen
b = 8



Browser-Unterstützung:

Chrome Firefox Edge Safari Opera
1,0 1,0 4,0 1,0 4,0
Alexandre Neukirchen
quelle
0

Dies ist mein Modell, das zeigt, wie man mit einer Generatorfunktion (ES6) in Javascript "schläft" oder "DoEvents" macht. Kommentierter Code:

<html>
<head>
<script>
  "use strict"; // always
  // Based on post by www-0av-Com /programming/3143928
  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*
  var divelt, time0, globaln = 0; // global variables
  var MainGenObj = Main(); // generator object = generator function()
window.onload = function() {
  divelt = document.getElementsByTagName("body")[0]; // for addline()
  addline("typeof Main: " + typeof Main);
  addline("typeof MainDriver: " + typeof MainDriver);
  addline("typeof MainGenObj: " + typeof MainGenObj);
  time0 = new Date().valueOf(); // starting time ms
  MainDriver(); // do all parts of Main()
}
function* Main() { // this is "Main" -- generator function -- code goes here
  // could be loops, or inline, like this:

  addline("Part A, time: " + time() + ", " + ++globaln); // part A
  yield 2000;                    // yield for 2000 ms (like sleep)

  addline("Part B, time: " + time() + ", " +  ++globaln); // part B
  yield 3000;                    // yield for 3000 ms (or like DoEvents)

  addline("Part Z, time: " + time() + ", " +  ++globaln); // part Z (last part)
  addline("End, time: " + time());
}
function MainDriver() { // this does all parts, with delays
  var obj = MainGenObj.next(); // executes the next (or first) part of Main()
  if (obj.done == false) { // if "yield"ed, this will be false
    setTimeout(MainDriver, obj.value); // repeat after delay
  }
}
function time() { // seconds from time0 to 3 decimal places
  var ret = ((new Date().valueOf() - time0)/1000).toString();
  if (ret.indexOf(".") == -1) ret += ".000";
  while (ret.indexOf(".") >= ret.length-3) ret += "0";
  return ret;
}
function addline(what) { // output
  divelt.innerHTML += "<br />\n" + what;
}
</script>
</head>
<body>
<button onclick="alert('I\'m alive!');"> Hit me to see if I'm alive </button>
</body>
</html>
dcromley
quelle
0

Versuchen Sie diese Funktion:

const delay = (ms, cb) => setTimeout(cb, ms)

So verwenden Sie es:

console.log("Waiting for 5 seconds.")
delay(5000, function() {
  console.log("Finished waiting for 5 seconds.")
})

Oder versprechen Sie Stil:

const delay = ms => new Promise(resolve => {
    setTimeout(resolve, ms)
})

Hier ist eine Demo .

Richie Bendall
quelle