Co to jest JavaScript wersja sleep()?

Czy istnieje lepszy sposób na zaprojektowanie sleep w JavaScript niż poniższa pausecomp Funkcja (wzięta stąd )?

function pausecomp(millis)
{
    var date = new Date();
    var curDate = null;
    do { curDate = new Date(); }
    while(curDate-date < millis);
}

Nie jest to duplikat Sleep w JavaScript - opóźnienie między akcjami ; chcę prawdziwego snu w środku funkcji, a nie opóźnienia przed wykonaniem kawałka kodu.

Author: fmsf, 2009-06-04

30 answers

2017 aktualizacja

Od 2009 roku, kiedy to pytanie zostało zadane, JavaScript znacznie ewoluował. Wszystkie inne odpowiedzi są teraz przestarzałe lub zbyt skomplikowane. Oto obecna najlepsza praktyka:

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

async function demo() {
  console.log('Taking a break...');
  await sleep(2000);
  console.log('Two seconds later');
}

demo();
To jest to. await sleep(<duration>).

Możesz wypróbować ten kod na żywo na Runkit. Zauważ, że,

  1. await może być wykonywane tylko w funkcjach poprzedzonych słowem kluczowym async. Runkit zawija kod w funkcję asynchroniczną przed wykonaniem to.
  2. await wstrzymuje tylko bieżącą async funkcję

Dwie nowe funkcje JavaScript pomogły napisać tę rzeczywistą funkcję "sleep":

Zgodność

Jeśli z jakiegoś powodu używasz węzła starszego niż 7 lub celujesz w Stare przeglądarki, async/await może być nadal używany przez Babel (narzędzie, które będzie transpile JavaScript + nowe funkcje do zwykłego starego JavaScript), z transform-async-to-generator plugin . Run

npm install babel-cli --save

Create .babelrc with:

{
  "plugins": [
    "transform-async-to-generator",
  ]
}

Następnie uruchom kod za pomocą

node_modules/babel-cli/bin/babel-node.js sleep.js

Ale ponownie, nie potrzebujesz tego, jeśli używasz węzła 7 lub nowszego, lub jeśli kierujesz do nowoczesnych przeglądarek.

 1211
Author: Dan Dascalescu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-05 06:00:44

(Zobacz zaktualizowaną odpowiedź dla 2016)

Myślę, że to całkowicie rozsądne, aby chcieć wykonać czynność, poczekać, a następnie wykonać inną czynność. Jeśli jesteś przyzwyczajony do pisania w językach wielowątkowych, prawdopodobnie masz pomysł, aby uzyskać wykonanie przez określony czas, aż wątek się obudzi.

Problem polega na tym, że JavaScript jest jednowątkowym modelem opartym na zdarzeniach. O ile w konkretnym przypadku byłoby miło, gdyby cały silnik poczekał kilka sekund, w ogólnie to zła praktyka. Załóżmy, że chciałbym skorzystać z twoich funkcji, pisząc własne? Kiedy zadzwoniłem do Twojej metody, moje metody zamarzłyby. Jeśli JavaScript mógłby w jakiś sposób zachować kontekst wykonywania funkcji, przechowywać ją gdzieś, a następnie przywrócić ją i kontynuować później, wtedy może się zdarzyć sleep, ale to w zasadzie byłoby threading.

Więc utknąłeś z tym, co zasugerowali inni - musisz podzielić swój kod na wiele funkcje.

Twoje pytanie to trochę fałszywy wybór. Nie ma sposobu, aby spać w sposób, w jaki chcesz, ani nie należy dążyć do rozwiązania, które sugerujesz.

 830
Author: Ben Flynn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:28

W JavaScript przepisuję każdą funkcję tak, aby mogła zakończyć się tak szybko, jak to możliwe. Chcesz odzyskać kontrolę nad przeglądarką, aby mogła wprowadzać zmiany w DOM.

Za każdym razem, gdy chciałem spać w środku mojej funkcji, zmieniałem zdanie, aby użyć setTimeout().

Zamierzam edytować tę odpowiedź, ponieważ uznałem ją za przydatną:

Niesławna funkcja snu lub opóźnienia w dowolnym języku jest bardzo dyskusyjna. Niektórzy powiedzą, że zawsze powinien być sygnał lub oddzwanianie aby odpalić daną funkcjonalność, inni będą twierdzić, że czasami przydatny jest dowolny moment opóźnienia. Mówię, że każda ich własna i jedna zasada nigdy nie może dyktować niczego w tej branży.

Pisanie funkcji snu jest proste i jeszcze bardziej użyteczne Dzięki obietnicom JavaScript:

// sleep time expects milliseconds
function sleep (time) {
  return new Promise((resolve) => setTimeout(resolve, time));
}

// Usage!
sleep(500).then(() => {
    // Do something after the sleep!
});
 597
Author: gsamaras,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-15 08:57:09

Tylko dla debug / dev , zamieszczam to jeśli komuś się przyda

Ciekawe rzeczy, w Firebug (i prawdopodobnie innych konsolach js) nic się nie dzieje po naciśnięciu enter, dopiero po podanym czasie uśpienia (...)

function sleepFor( sleepDuration ){
    var now = new Date().getTime();
    while(new Date().getTime() < now + sleepDuration){ /* do nothing */ } 
}

Przykład użycia:

function sleepThenAct(){ sleepFor(2000); console.log("hello js sleep !"); }
 270
Author: StephaneAG,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-10 13:41:14

Zgadzam się z innymi plakatami, zajęty sen to zły pomysł.

SetTimeout nie wstrzymuje wykonania, wykonuje następną linię funkcji zaraz po ustawieniu limitu czasu, a nie po jego wygaśnięciu, więc nie wykonuje tego samego zadania, co sen.

Sposobem na to jest podział funkcji na części przed i po.

function doStuff()
{
  //do some things
  setTimeout(continueExecution, 10000) //wait ten seconds before continuing
}

function continueExecution()
{
   //finish doing things after the pause
}

Upewnij się, że nazwy funkcji nadal dokładnie opisują, czym jest każdy element doing (tj. GatherInputThenWait i CheckInput, zamiast funcPart1 i funcPart2)

Edit

Ta metoda ma na celu nie wykonywanie linii kodu, które zdecydujesz, aż po upływie limitu czasu, jednocześnie zwracając kontrolę z powrotem do komputera klienta, aby wykonać to, co jeszcze zostało ustawione w kolejce.

Further Edit

Jak zaznaczono w komentarzach, to absolutnie nie będzie działać w pętli. Można zrobić jakieś fantazyjne (brzydkie) hacking, aby to działało w pętli, ale w ogóle, że będzie po prostu katastrofalny kod spaghetti.

 166
Author: DevinB,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-10 18:52:41

Z miłości do $ DEITY proszę nie robić funkcji spania zapracowanego oczekiwania. setTimeout i setInterval Zrób wszystko, czego potrzebujesz.

 114
Author: chaos,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-11 20:59:44

Wiem, że to trochę stare pytanie, ale jeśli (tak jak ja) używasz Javascript z Rhino, możesz użyć...

try
{
  java.lang.Thread.sleep(timeInMilliseconds);
}
catch (e)
{
  /*
   * This will happen if the sleep is woken up - you might want to check
   * if enough time has passed and sleep again if not - depending on how
   * important the sleep time is to you.
   */
}
 110
Author: mjaggard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-04 14:16:06

Jeśli używasz jQuery, ktoś stworzył wtyczkę" delay", która jest niczym więcej niż opakowaniem dla setTimeout:

// Delay Plugin for jQuery
// - http://www.evanbot.com
// - © 2008 Evan Byrne

jQuery.fn.delay = function(time,func){
    this.each(function(){
        setTimeout(func,time);
    });

    return this;
};

Możesz użyć go w wierszu wywołań funkcji zgodnie z oczekiwaniami:

$('#warning')
.addClass('highlight')
.delay(1000)
.removeClass('highlight');
 65
Author: Alan Plum,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-10 18:50:32

Ja też szukałem rozwiązania sleep (nie dla kodu produkcyjnego, tylko dla dev / tests) i znalazłem ten artykuł:

Http://narayanraman.blogspot.com/2005/12/javascript-sleep-or-wait.html

...a oto kolejny link z rozwiązaniami po stronie Klienta: http://www.devcheater.com/

Również, gdy wywołujesz alert(), Twój kod również zostanie wstrzymany, podczas gdy alert jest wyświetlany -- trzeba znaleźć sposób, aby nie wyświetlać alertu, ale uzyskać ten sam efekt. :)

 42
Author: a_w,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-06 07:26:05

Proszę. Jak mówi kod, nie bądź złym deweloperem i używaj tego na stronach internetowych. To funkcja deweloperska.

// Basic sleep function based on ms.
// DO NOT USE ON PUBLIC FACING WEBSITES.
function sleep(ms) {
    var unixtime_ms = new Date().getTime();
    while(new Date().getTime() < unixtime_ms + ms) {}
}
 29
Author: Ian Maddox,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-03 02:02:47

Oto proste rozwiązanie przy użyciu synchronicznego XMLHttpRequest:

function sleep(n){
  var request = new XMLHttpRequest();
  request.open('GET', '/sleep.php?n=' + n, false);  // `false` makes the request synchronous
  request.send(null);
}

Zawartość snu.php:

<?php sleep($_GET['n']);

Teraz zadzwoń z: sen (5);

 25
Author: pguardiario,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-13 01:42:38

Pierwszy:

Zdefiniuj funkcję, którą chcesz wykonać w następujący sposób:

function alertWorld(){
  alert("Hello World");
}

Następnie zaplanuj jego wykonanie za pomocą metody setTimeout:

setTimeout(alertWorld,1000)

Zwróć uwagę na dwie rzeczy

  • drugim argumentem jest czas w milisekundach
  • jako pierwszy argument musisz podać tylko nazwę (odniesienie) funkcji, bez nawiasu
 15
Author: Pablo Fernandez,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-04 14:47:52

Ja osobiście lubię proste:

function sleep(seconds){
    var waitUntil = new Date().getTime() + seconds*1000;
    while(new Date().getTime() < waitUntil) true;
}

Wtedy:

sleep(2); // Sleeps for 2 seconds

Używam go cały czas do tworzenia fałszywego czasu ładowania podczas tworzenia skryptów w P5js

 15
Author: Akelian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-12 19:56:33

Lepszym rozwiązaniem, aby rzeczy wyglądały tak, jak większość ludzi chce, jest użycie funkcji anonimowej:

alert('start');
var a = 'foo';
//lots of code
setTimeout(function(){  //Beginning of code that should run AFTER the timeout
    alert(a);
    //lots more code
},5000);  // put the timeout here

To jest prawdopodobnie najbliżej dostaniesz się do czegoś, co po prostu robi to, co chcesz.

Uwaga, jeśli potrzebujesz wielu miejsc do spania, może to zrobić się brzydkie w pośpiechu i być może będziesz musiał przemyśleć swój projekt.

 12
Author: Mainguy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-08 13:05:30

Zamknąłbym setTimeOut w obietnicy dla spójności kodu z innymi zadaniami asynchronicznymi: Demo w Fiddle

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

Używane w ten sposób:

sleep(2000).then(function() { 
   // Do something
});

Łatwo zapamiętać składnię, jeśli używałeś obietnic.

 9
Author: Elo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-09 13:59:21

W przypadku przeglądarek zgadzam się, że setTimeout i setInterval są dobrą drogą.

Ale w przypadku kodu po stronie serwera może on wymagać funkcji blokującej(na przykład, aby można było efektywnie synchronizować wątki).

Jeśli używasz node.js i meteor, być może napotkałeś ograniczenia używania setTimeout w włóknie. Oto kod do uśpienia po stronie serwera.

var Fiber = require('fibers');

function sleep(ms) {
    var fiber = Fiber.current;
    setTimeout(function() {
        fiber.run();
    }, ms);
    Fiber.yield();
}

Fiber(function() {
    console.log('wait... ' + new Date);
    sleep(1000);
    console.log('ok... ' + new Date);
}).run();
console.log('back in main');

Zobacz: https://github.com/laverdet/node-fibers#sleep

 8
Author: Homer6,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-17 22:53:18

Większość odpowiedzi tutaj są błędne lub co najmniej nieaktualne. Nie ma powodu, javascript musi być jednym wątku, i rzeczywiście nie jest. dzisiaj wszystkie główne przeglądarki obsługują pracowników, wcześniej było to w przypadku innych JavaScript runtimes jak Rhino i Node.js obsługiwane wielowątkowość.

'Javascript is single threaded' is not a valid answer. Na przykład uruchomienie funkcji sleep w workerze nie zablokowałoby żadnego kodu uruchomionego w wątku interfejsu użytkownika.

W nowsze środowiska uruchomieniowe obsługujące generatory i wydajność, można wprowadzić podobną funkcjonalność do funkcji sleep w środowisku z pojedynczym wątkiem:

// This is based on the latest ES6 drafts.
// js 1.7+ (SpiderMonkey/Firefox 2+) syntax is slightly different

// run code you want to sleep here (ommit star if using js 1.7)
function* main(){
    for (var i = 0; i < 10; i++) {
        // to sleep for 10 milliseconds 10 times in a row
        yield 10;
    }

    yield 5;
    console.log('I just slept 5 milliseconds!');
}

// resume the given generator after ms milliseconds
function resume(ms, generator){
    setTimeout(function(){
        // ommit .value if using js 1.7
        var nextSleep = generator.next().value;
        resume(nextSleep, generator);
    }, ms);
}

// initialize generator and get first sleep for recursive function
var
    generator = main(),
    firstSleep = generator.next().value;

// initialize recursive resume function
resume(firstSleep, generator);
Ta imitacja snu różni się od prawdziwej funkcji snu, ponieważ nie blokuje wątku. Jest to po prostu cukier na szczycie obecnej funkcji setTimeout javascript. Ten typ funkcjonalności został zaimplementowany w zadaniu .js i powinien dzialac dzis w Firefoksie.
 8
Author: Gabriel Ratener,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-16 08:22:24

Przeszukałem / wygooglowałem sporo stron internetowych na JavaScript sleep / wait... i nie ma odpowiedzi, jeśli chcesz javascript "RUN, DELAY, RUN"... większość ludzi dostała albo "RUN, RUN( bezużyteczne rzeczy), RUN" lub "RUN, RUN + opóźniony bieg"....

Więc zjadłam hamburgery i pomyślałam::: oto rozwiązanie, które działa... ale musisz poćwiartować kody biegowe...::: tak, Wiem, to jest po prostu łatwiejsze do odczytania refaktoryzacja... mimo to...

//......................................... // przykład1:

<html>
<body>
<div id="id1">DISPLAY</div>

<script>
//javascript sleep by "therealdealsince1982"; copyrighted 2009
//setInterval
var i = 0;

function run() {
    //pieces of codes to run
    if (i==0){document.getElementById("id1").innerHTML= "<p>code segment "+ i +" is ran</p>"; }
    if (i==1){document.getElementById("id1").innerHTML= "<p>code segment "+ i +" is ran</p>"; }
    if (i==2){document.getElementById("id1").innerHTML= "<p>code segment "+ i +" is ran</p>"; }
    if (i >2){document.getElementById("id1").innerHTML= "<p>code segment "+ i +" is ran</p>"; }
    if (i==5){document.getElementById("id1").innerHTML= "<p>all code segment finished running</p>"; clearInterval(t); } //end interval, stops run
    i++; //segment of code finished running, next...
}

run();
t=setInterval("run()",1000);

</script>
</body>
</html>

//.................................... // przykład2:

<html>
<body>
<div id="id1">DISPLAY</div>

<script>
//javascript sleep by "therealdealsince1982"; copyrighted 2009
//setTimeout
var i = 0;

function run() {
    //pieces of codes to run, can use switch statement
    if (i==0){document.getElementById("id1").innerHTML= "<p>code segment "+ i +" ran</p>"; sleep(1000);}
    if (i==1){document.getElementById("id1").innerHTML= "<p>code segment "+ i +" ran</p>"; sleep(2000);}
    if (i==2){document.getElementById("id1").innerHTML= "<p>code segment "+ i +" ran</p>"; sleep(3000);}
    if (i==3){document.getElementById("id1").innerHTML= "<p>code segment "+ i +" ran</p>";} //stops automatically
    i++;
}

function sleep(dur) {t=setTimeout("run()",dur);} //starts flow control again after dur

run(); //starts
</script>
</body>
</html>

//................. przykład3:

<html>
<body>
<div id="id1">DISPLAY</div>

<script>
//javascript sleep by "therealdealsince1982"; copyrighted 2009
//setTimeout
var i = 0;

function flow() {
    run(i);
    i++; //code segment finished running, increment i; can put elsewhere
    sleep(1000);
    if (i==5) {clearTimeout(t);} //stops flow, must be after sleep()
}

function run(segment) {
    //pieces of codes to run, can use switch statement
    if (segment==0){document.getElementById("id1").innerHTML= "<p>code segment "+ segment +" is ran</p>"; }
    if (segment==1){document.getElementById("id1").innerHTML= "<p>code segment "+ segment +" is ran</p>"; }
    if (segment==2){document.getElementById("id1").innerHTML= "<p>code segment "+ segment +" is ran</p>"; }
    if (segment >2){document.getElementById("id1").innerHTML= "<p>code segment "+ segment +" is ran</p>"; }
}

function sleep(dur) {t=setTimeout("flow()",dur);} //starts flow control again after dur

flow(); //starts flow
</script>
</body>
</html>

//.............. przykład4:

<html>
<body>
<div id="id1">DISPLAY</div>

<script>
//javascript sleep by "therealdealsince1982"; copyrighted 2009
//setTimeout, switch
var i = 0;

function flow() {
    switch(i)
    {
        case 0:
            run(i);
            sleep(1000);
            break;
        case 1:
            run(i);
            sleep(2000);
            break;
        case 5:
            run(i);
            clearTimeout(t); //stops flow
            break;
        default:
            run(i);
            sleep(3000);
            break;
    }
}

function run(segment) {
    //pieces of codes to run, can use switch statement
    if (segment==0){document.getElementById("id1").innerHTML= "<p>code segment "+ segment +" is ran</p>"; }
    if (segment==1){document.getElementById("id1").innerHTML= "<p>code segment "+ segment +" is ran</p>"; }
    if (segment==2){document.getElementById("id1").innerHTML= "<p>code segment "+ segment +" is ran</p>"; }
    if (segment >2){document.getElementById("id1").innerHTML= "<p>code segment "+ segment +" is ran</p>"; }
    i++; //current segment of code finished running, next...
}

function sleep(dur) {t=setTimeout("flow()",dur);} //starts flow control again after dur

flow(); //starts flow control for first time...
</script>
</body>
</html>
 7
Author: user207408,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-11-10 06:06:23
function sleep(milliseconds) {
  var start = new Date().getTime();
  for (var i = 0; i < 1e7; i++) {
    if ((new Date().getTime() - start) > milliseconds){
      break;
    }
  }
}
 7
Author: Shemeer M Ali,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-09 18:37:54

Mogę zrozumieć cel funkcji snu, jeśli masz do czynienia z synchronicznym wykonaniem. Funkcje setInterval i setTimeout tworzą równoległy wątek wykonania, który zwraca sekwencję wykonania z powrotem do głównego programu, co jest nieskuteczne, jeśli trzeba czekać na dany wynik. Oczywiście można użyć events i handlers, ale w niektórych przypadkach nie jest to, co jest zamierzone.

 6
Author: naazgull,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-06-21 17:41:26

Jednym ze scenariuszy, w którym możesz chcieć użyć funkcji sleep() zamiast setTimeout (), jest sytuacja, gdy masz funkcję odpowiadającą na kliknięcie użytkownika, które ostatecznie otworzy nowe, tj. wyskakujące okno i zainicjowałeś przetwarzanie, które wymaga krótkiego czasu, aby zakończyć, zanim wyskakujące okno zostanie wyświetlone. Przeniesienie otwartego okna do zamknięcia oznacza, że zazwyczaj jest ono blokowane przez przeglądarkę.

 5
Author: acuth,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-10-18 19:45:43

Dodawanie moich dwóch bitów. Potrzebowałem zapracowanego oczekiwania do celów testowych. Nie chciałem dzielić kodu, ponieważ byłoby to dużo pracy, więc proste dla zrobił to dla mnie.

for (var i=0;i<1000000;i++){                    
     //waiting
  }
Nie widzę żadnych minusów w robieniu tego i to mi pomogło.
 5
Author: caiocpricci2,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-20 11:57:30

Można to zrobić za pomocą Java ' s sleep method. Testowałem go w FF i IE i nie blokuje komputera, nie żuje zasobów ani nie powoduje niekończących się trafień serwera. Dla mnie to czyste rozwiązanie.

Najpierw musisz załadować Javę na stronę i udostępnić jej metody. Aby to zrobić, zrobiłem to:

<html>
<head>

<script type="text/javascript">

  function load() {
    var appletRef = document.getElementById("app");
    window.java = appletRef.Packages.java;
  } // endfunction

</script>

<body onLoad="load()">

<embed id="app" code="java.applet.Applet" type="application/x-java-applet" MAYSCRIPT="true" width="0" height="0" />

Wtedy, wszystko co musisz zrobić, gdy chcesz bezbolesną pauzę w swoim JS to:

java.lang.Thread.sleep(xxx)

Gdzie xxx to czas w milisekundach. W moim przypadku (w uzasadnieniu), to był częścią back-end realizacji zamówień w bardzo małej firmie i musiałem wydrukować fakturę, która musiała być załadowana z serwera. Zrobiłem to ładując fakturę (jako stronę internetową) do ramki iFrame, a następnie drukując ramkę iFrame. Oczywiście musiałem poczekać, aż strona zostanie w pełni załadowana, zanim mogłem wydrukować, więc JS musiał pauzować. Udało mi się to dzięki zmianie ukrytego pola formularza na stronie nadrzędnej ze zdarzeniem onLoad na stronie faktury (w ramce iFrame). Oraz kod na stronie nadrzędnej do wydruk faktury wyglądał tak (nieistotne części wycięte dla jasności):

var isReady = eval('document.batchForm.ready');
isReady.value=0;

frames['rpc_frame'].location.href=url;

while (isReady.value==0) {
  java.lang.Thread.sleep(250);
} // endwhile

window.frames['rpc_frame'].focus();
window.frames['rpc_frame'].print();

Więc użytkownik naciska przycisk, skrypt ładuje stronę faktury, a następnie czeka, sprawdzając co kwadrans, aby sprawdzić, czy strona faktury jest zakończona Ładowanie, a następnie wyskakuje okno drukowania dla użytkownika, aby wysłać go do drukarki. QED.

 5
Author: Rachael,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-14 01:32:07

Wiele odpowiedzi nie odpowiada (bezpośrednio)na pytanie, tak samo jak ta...

Oto moje dwa grosze (lub funkcje):

Jeśli chcesz mieć mniej niezgrabnych funkcji niż setTimeout i setInterval, możesz je zawinąć w funkcje, które po prostu odwracają kolejność argumentów i nadają im ładne nazwy:

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

Wersje CoffeeScript:

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

Możesz je następnie ładnie używać z funkcjami anonimowymi:

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

Teraz czyta się łatwo jako " po N milisekundach, ..."(lub "co N milisekund, ...")

 5
Author: 1j01,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-16 03:41:10

Nie możesz zrobić takiego snu w JavaScript, a raczej nie powinieneś. uruchomienie pętli sleep lub a while spowoduje zawieszenie przeglądarki użytkownika do czasu zakończenia pętli.

Użyj timera, jak określono w odnośniku.

 4
Author: Andrew Dunkman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-04 14:46:51

W konkretnym przypadku, gdy chcemy rozdzielić zestaw wywołań wykonywanych przez pętlę, możesz użyć czegoś takiego jak poniższy kod z prototype. Bez prototypu możesz zastąpić funkcję opóźnienia setTimeout.

function itemHandler(item)
{
    alert(item);
}

var itemSet = ['a','b','c'];

// Each call to itemHandler will execute
// 1 second apart
for(var i=0; i<itemSet.length; i++)
{
    var secondsUntilExecution = i;
    itemHandler.delay(secondsUntilExecution, item)
}
 4
Author: beauburrier,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-27 19:45:00

Jeśli jesteś na node.js, możesz spojrzeć na fibers - natywne rozszerzenie C do węzła, symulacja wielowątkowa.

Pozwala na wykonanie prawdziwego sleep w sposób, który blokuje wykonanie we włóknach, ale nie blokuje w wątku głównym i innych włóknach.

Oto przykład prosto z własnego readme:

// sleep.js

var Fiber = require('fibers');

function sleep(ms) {
    var fiber = Fiber.current;
    setTimeout(function() {
        fiber.run();
    }, ms);
    Fiber.yield();
}

Fiber(function() {
    console.log('wait... ' + new Date);
    sleep(1000);
    console.log('ok... ' + new Date);
}).run();
console.log('back in main');

– a wyniki to:

$ node sleep.js
wait... Fri Jan 21 2011 22:42:04 GMT+0900 (JST)
back in main
ok... Fri Jan 21 2011 22:42:05 GMT+0900 (JST)
 4
Author: tomekwi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-06 10:55:38

Stare pytanie z 2009 roku. Teraz w 2015 możliwe jest nowe rozwiązanie z generatorami zdefiniowanymi w ECMAscript 2015 aka ES6. Został on zatwierdzony w czerwcu, ale wcześniej był implementowany w Firefoksie i Chrome. Teraz funkcja uśpienia może być nie zajęta, nieblokowana i zagnieżdżona wewnątrz pętli i funkcji podrzędnych bez zamrażania przeglądarki. Potrzebny jest tylko czysty JavaScript, bez bibliotek i frameworków.

Poniższy program pokazuje jak można wykonać sleep() i runSleepyTask(). Funkcja {[2] } jest tylko yield oświadczenie. Jest to tak proste, że w rzeczywistości łatwiej jest napisać yield polecenie bezpośrednio zamiast wywołania sleep(), ale wtedy nie byłoby słowa snu: -) yield Zwraca wartość czasu do metody next() wewnątrz wakeup() i czeka. Rzeczywiste "spanie" odbywa się w wakeup() przy użyciu starego, dobrego setTimeout(). Przy wywołaniu zwrotnym metoda next() uruchamia polecenie yield, aby kontynuować, a "magiczną" cechą yield jest to, że wszystkie zmienne lokalne i cały stos wywołań wokół niego jest nadal nienaruszone.

Funkcje, które używają funkcji sleep () lub yield muszą być zdefiniowane jako generatory. Łatwo zrobić, dodając asterix do słowa kluczowego function*. Wykonanie generatora jest nieco trudniejsze. Po wywołaniu ze słowem kluczowym new generator zwraca obiekt, który posiada metodę next(), ale ciało generatora nie jest wykonywane(słowo kluczowe new jest opcjonalne i nie ma znaczenia). Metoda next() uruchamia wykonanie ciała generatora, dopóki nie napotka yield. Funkcja owijarki runSleepyTask() uruchamia ping-ponga: next() czeka na yield, a yield czeka na next().

Innym sposobem wywołania generatora jest użycie słowa kluczowego yield*, tutaj działa jak proste wywołanie funkcji, ale zawiera również możliwość powrotu do next().

To wszystko pokazuje przykład drawTree(). Rysuje drzewo z liśćmi na obracającej się scenie 3D. Drzewo rysowane jest jako pień z 3 częściami u góry w różnych kierunkach. Każda część jest następnie rysowana jako kolejne, ale mniejsze drzewo przez wywołanie drawTree() rekurencyjnie po krótkim śnie. Bardzo małe drzewo jest rysowane jako tylko liść.

Każdy liść ma swoje życie w oddzielnym zadaniu zaczynającym się od runSleepyTask(). Rodzi się, rośnie, siedzi, zanika, upada i umiera w growLeaf(). Prędkość jest kontrolowana za pomocą sleep(). Pokazuje to, jak łatwo można wykonać wielozadaniowość.

function* sleep(milliseconds) {yield milliseconds};

function runSleepyTask(task) {
    (function wakeup() {
        var result = task.next();
        if (!result.done) setTimeout(wakeup, result.value);
    })()
}
//////////////// written by Ole Middelboe  /////////////////////////////

pen3D =setup3D();
var taskObject = new drawTree(pen3D.center, 5);
runSleepyTask(taskObject);

function* drawTree(root3D, size) {
    if (size < 2) runSleepyTask(new growLeaf(root3D))
    else {
        pen3D.drawTrunk(root3D, size);
        for (var p of [1, 3, 5]) {
            var part3D = new pen3D.Thing;
            root3D.add(part3D);
            part3D.move(size).turn(p).tilt(1-p/20);
            yield* sleep(50);
            yield* drawTree(part3D, (0.7+p/40)*size);
        }
    }
}

function* growLeaf(stem3D) {
    var leaf3D = pen3D.drawLeaf(stem3D);
    for (var s=0;s++<15;) {yield* sleep(100); leaf3D.scale.multiplyScalar(1.1)}
    yield* sleep( 1000 + 9000*Math.random() );
    for (var c=0;c++<30;) {yield* sleep(200); leaf3D.skin.color.setRGB(c/30, 1-c/40, 0)}
    for (var m=0;m++<90;) {yield* sleep( 50); leaf3D.turn(0.4).tilt(0.3).move(2)}
    leaf3D.visible = false;
}
///////////////////////////////////////////////////////////////////////

function setup3D() {
    var scene, camera, renderer, diretionalLight, pen3D;

    scene = new THREE.Scene();
    camera = new THREE.PerspectiveCamera(75, 
        window.innerWidth / window.innerHeight, 0.1, 1000);
    camera.position.set(0, 15, 20);
    renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.body.appendChild(renderer.domElement);
    
    directionalLight = new THREE.DirectionalLight(0xffffaa, 0.7);
    directionalLight.position.set(-1, 2, 1);
    scene.add(directionalLight);
    scene.add(new THREE.AmbientLight(0x9999ff));
      
    (function render() {
        requestAnimationFrame(render);
        // renderer.setSize( window.innerWidth, window.innerHeight );
        scene.rotateY(10/60/60);
        renderer.render(scene, camera);
    })();
    
    window.addEventListener(
        'resize',
        function(){
            renderer.setSize( window.innerWidth, window.innerHeight );
            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();
       }, 
       false
    );
    
    pen3D = {
        drawTrunk: function(root, size) {
            // root.skin = skin(0.5, 0.3, 0.2);
            root.add(new THREE.Mesh(new THREE.CylinderGeometry(size/12, size/10, size, 16), 
                root.skin).translateY(size/2));
            root.add(new THREE.Mesh(new THREE.SphereGeometry(size/12, 16), 
                root.skin).translateY(size));
            return root;
        },
        
        drawLeaf: function(stem) {
            stem.skin.color.setRGB(0, 1, 0);
            stem.add(new THREE.Mesh(new THREE.CylinderGeometry(0, 0.02, 0.6), 
                stem.skin) .rotateX(0.3).translateY(0.3));
            stem.add(new THREE.Mesh(new THREE.CircleGeometry(0.2), 
                stem.skin) .rotateX(0.3).translateY(0.4));
            return stem;
        },
        
        Thing: function() {
            THREE.Object3D.call(this);
            this.skin = new THREE.MeshLambertMaterial({
                color: new THREE.Color(0.5, 0.3, 0.2),
                vertexColors: THREE.FaceColors,
                side: THREE.DoubleSide
            })
        }
    };

    pen3D.Thing.prototype = Object.create(THREE.Object3D.prototype);
    pen3D.Thing.prototype.tilt = pen3D.Thing.prototype.rotateX;
    pen3D.Thing.prototype.turn = pen3D.Thing.prototype.rotateY;
    pen3D.Thing.prototype.move = pen3D.Thing.prototype.translateY;
    
    pen3D.center = new pen3D.Thing;
    scene.add(pen3D.center);
    
    return pen3D;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r71/three.min.js"></script>

Rzeczy 3D są ukryte w setup3d () i są dołączone tylko po to, aby uczynić je mniej nudnymi niż konsola.log (). Anioły są mierzone w radiany przy okazji.

Przetestowano do pracy w Firefoksie i Chrome. Nie zaimplementowane w Internet Explore i iOS (ipad). Spróbuj sam to uruchomić.

Po kolejnym przejściu odpowiedzi, które znalazłem, że Gabriel Ratener zrobił podobną odpowiedź rok temu: https://stackoverflow.com/a/24401317/5032384

 4
Author: Ole Middelboe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:35

Po pierwsze - setTimeout i setInterval są tym, co powinno być używane, ze względu na naturę wywołania zwrotnego javascript. Jeśli chcesz użyć sleep() to przepływ sterowania lub Architektura Twojego kodu jest niepoprawna.

Powiedziawszy, że przypuszczam, że nadal mogę pomóc w dwóch realizacji snu.

  1. Udawanie synchronicznego biegu z czubka mojej głowy:

    //a module to do taht //dual-license: MIT or WTF [you can use it anyhow and leave my nickname in a comment if you want to]
    var _=(function(){
     var queue=[];
     var play=function(){
       var go=queue.shift();
         if(go){if(go.a){go.f();play();}else{setTimeout(play,go.t);}}
       }
     return {
       go:function(f){
        queue.push({a:1,f:f});
        },
       sleep:function(t){
        queue.push({a:0,t:t});
        },
       playback:play 
     }
    })();
    

    [automatyczne odtwarzanie powinno być również możliwe]

    //usage
    
    _.go(function(){
    
    //your code
    console.log('first');
    
    });
    
    
    _.sleep(5000);
    
    _.go(function(){
    
    //your code
    console.log('next');
    
    });
    
    //this triggers the simulation
    _.playback();
    
  2. Real synchroniczny bieg

Pewnego dnia dużo o tym myślałem i jedyny pomysł, jaki miałem na prawdziwy sen w javascript, to techniczny.

Funkcja sleep musiałaby być synchronicznym wywołaniem AJAX z timeoutem ustawionym na wartość sleep. To wszystko i jedyny sposób na prawdziwe sleep()

 3
Author: naugtur,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-09 08:53:48

Jeśli masz taką funkcję snu

var sleep = function(period, decision, callback){
    var interval = setInterval(function(){
        if (decision()) {
            interval = clearInterval(interval);
            callback();
        }
    }, period);
}

I masz funkcję asynchroniczną do wielokrotnego wywoływania

var xhr = function(url, callback){
    // make ajax request
    // call callback when request fulfills
}

I tak ustawiasz swój projekt:

var ready = false;

function xhr1(){
    xhr(url1, function(){ ready = true;});  
}
function xhr2(){
    xhr(url2, function(){ ready = true; }); 
}
function xhr3(){
    xhr(url3, function(){ ready = true; }); 
}

Wtedy możesz to zrobić:

xhr1();
sleep(100, function(){ return done; }, xhr2);
sleep(100, function(){ return done; }, xhr3);
sleep(100, function(){ return done; }, function(){
    // do more
});

Zamiast niekończącego się wcięcia wywołania zwrotnego w ten sposób:

xhr(url1, function(){
    xhr2(url2, function(){
        xhr3(url3, function(){
            // do more
        });
    });
});
 3
Author: BishopZ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-29 21:20:11