Qual è la versione JavaScript di sleep ()?


2337

Esiste un modo migliore per progettare un sleepin JavaScript rispetto alla seguente pausecompfunzione ( presa da qui )?

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

Questo non è un duplicato di Sleep in JavaScript - ritardo tra le azioni ; Voglio un vero sonno nel mezzo di una funzione, e non un ritardo prima dell'esecuzione di un pezzo di codice.


4
È impostato nel mezzo di un po ', se uso setTimeout mentre continuerò a elaborare e mettere in coda più setTimeouts che alla fine saranno in esecuzione allo stesso tempo e
creeranno

160
Questa è una soluzione orribile: stai masticando i cicli di elaborazione senza fare nulla.
17 del 26

12
L'unico scopo per un sonno è il polling o l'attesa di una richiamata: setInterval e setTimeout fanno entrambi meglio di così.
annakata,

1
Probabilmente puoi fare quello che vuoi con lo stile di passaggio di continuazione in JavaScript. Dai un'occhiata a questo articolo.
Ognyan Dimitrov,

Risposte:


2565

Aggiornamento 2017-2019

Dal 2009, quando è stata posta questa domanda, JavaScript si è evoluto in modo significativo. Tutte le altre risposte sono ora obsolete o eccessivamente complicate. Ecco le migliori pratiche attuali:

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, showing sleep in a loop...');

  // Sleep in loop
  for (let i = 0; i < 5; i++) {
    if (i === 3)
      await sleep(2000);
    console.log(i);
  }
}

demo();

Questo è. await sleep(<duration>).

O come one-liner:

await new Promise(r => setTimeout(r, 2000));

Nota che,

  1. awaitpuò essere eseguito solo in funzioni con il prefisso della asyncparola chiave o al livello più alto dello script in alcuni ambienti (ad esempio la console di Chrome DevTools o Runkit).
  2. awaitmette in pausa solo la asyncfunzione corrente

Due nuove funzionalità JavaScript hanno contribuito a scrivere questa funzione "sleep":

Compatibilità

Se per qualche strano motivo stai usando Nodo più vecchio di 7 (che ha raggiunto la fine del ciclo di vita ), o stai prendendo di mira vecchi browser, async/ awaitpuò ancora essere usato tramite Babel (uno strumento che trascriverà JavaScript + nuove funzionalità in un semplice vecchio JavaScript) , con il transform-async-to-generatorplug-in.


5
Roba fantastica qui. Mi chiedo, in che modo ciò influisce o si relaziona con gli stati "attivi" / "inattivi" dei browser moderni dopo che JS ha chiamato la modalità "sospensione"? Il browser può bloccare la sospensione come previsto per JS generale, richiamarlo in seguito quando diventa "attivo" o ha un comportamento diverso?
Andre Canilho,

18
Qual è l'attuale supporto del browser per questo? Non considererei le soluzioni precedenti "obsolete" fino a quando questa soluzione non sarà supportata dalla stragrande maggioranza dei browser, o almeno da quelli comuni. Al contrario, considererei questa soluzione interessante ma inutilizzabile / poco pratica fino a quando non avrà un supporto diffuso.
Alvin Thompson,

75
Questo non è "sonno reale" e non risponde alla domanda. La persona che ha fatto una domanda ha fatto una chiara distinzione tra stackoverflow.com/questions/758688/sleep-in-javascript e la sua domanda. Nel sonno reale nessun altro codice può essere eseguito (se non in un altro thread). Questa risposta è buona per l'altra domanda.
niry

4
@jacroe - il transpiler gestisce le funzioni delle frecce e asincronizza / attende (il che provocherebbe comunque il vomito di sangue da parte di IE)
Jaromanda X,

11
@niry JavaScript, essendo un linguaggio a thread singolo, non è adatto per il sonno "reale", poiché viene eseguito sullo stesso thread dell'interfaccia utente e causerebbe la mancata risposta delle pagine Web.
Patrick Roberts,

849

(Vedi la risposta aggiornata per il 2016 )

Penso che sia perfettamente ragionevole voler eseguire un'azione, attendere, quindi eseguire un'altra azione. Se sei abituato a scrivere in linguaggi multi-thread, probabilmente hai l'idea di cedere l'esecuzione per un determinato periodo di tempo fino a quando il thread non si riattiva.

Il problema qui è che JavaScript è un modello basato su eventi a thread singolo. Mentre in un caso specifico, potrebbe essere bello avere l'intero motore in attesa per alcuni secondi, in generale è una cattiva pratica. Supponi di voler utilizzare le tue funzioni mentre scrivo le mie? Quando ho chiamato il tuo metodo, i miei metodi si bloccavano tutti. Se JavaScript potesse in qualche modo preservare il contesto di esecuzione della tua funzione, archiviarlo da qualche parte, quindi ripristinarlo e continuare più tardi, quindi potrebbe accadere il sonno, ma sostanzialmente sarebbe thread.

Quindi sei praticamente bloccato da ciò che altri hanno suggerito: dovrai suddividere il codice in più funzioni.

Quindi la tua domanda è un po 'falsa. Non c'è modo di dormire nel modo desiderato, né dovresti cercare la soluzione che suggerisci.


45
Questa non è affatto una risposta corretta. Se Javascript non ha una funzione sleep, è solo perché ECMAScript non lo richiede. È una scelta progettuale da parte dell'ente responsabile della progettazione di Javascript. Si sarebbe potuto fare in modo che il tempo di esecuzione Javascript fosse in attesa per un determinato periodo di tempo prima di eseguire la riga di codice successiva, ma è stato scelto di non farlo.
Didier A.

5
Un sonno può essere perfettamente implementato in JavaScript anche se non con precisione in tempo reale. Dopotutto è un sistema basato su eventi. Se le chiamate asincrone sono completate, viene attivato un evento. Non vedo alcun motivo per cui lo stesso non sia possibile quando viene emesso un sleep () dopo il quale il controllo viene restituito al browser fino al termine del sonno, restituendo il controllo alla funzione chiamante. E sì, sono anche d'accordo sul fatto che a volte dormire sia utile soprattutto quando gli sviluppatori PRIMA di aver rovinato così tanto il design che NON hai altra via d'uscita oltre al completo refactoring per il quale non hai tempo
Lawrence

Prova Hypnotic, che segue questa idea: coolwanglu.github.io/hypnotic/web/demo.html
Tezcat,

4
Chiamare javascript a thread singolo è un ma di un mito. Mentre può essere tecnicamente corretto, funzionalmente si comporta come una lingua multithread. Simulare un fork () è banalmente facile e sebbene yield () non sia realmente implementabile, puoi avvicinarti abbastanza usando la memoria condivisa per bloccare / semaforo. Per il programmatore medio, ha senso trattarlo come multi-thread; il nome tecnico è importante solo per gli sviluppatori della lingua.
Benubird,

8
Sono d'accordo sul perché sleep()non sia possibile in JS e che la maggior parte delle volte ci siano modi migliori per fare le cose. Ma considererei ancora il modo in cui il motore lega tutte le cose come un difetto di progettazione; non c'è motivo per cui la lingua non possa avere una sleep()funzione limitata a uno script, una pagina o una funzione specifica senza che il motore blocchi la CPU e blocchi l'app come un maniaco. È il 2015 e non dovresti riuscire a bloccare un intero browser web con while(1). Abbiamo Flash per cose del genere.
Beejor,

660

In JavaScript, riscrivo ogni funzione in modo che possa terminare il più presto possibile. Desideri riprendere il controllo del browser in modo che possa apportare modifiche al DOM.

Ogni volta che volevo dormire nel mezzo della mia funzione, mi sono rifatturato di usare a setTimeout().

modificare

Il famigerato sonno, o ritardo, funzione in qualsiasi lingua è molto dibattuto. Alcuni diranno che dovrebbe esserci sempre un segnale o una richiamata per attivare una determinata funzionalità, altri sosterranno che a volte è utile un momento arbitrario di ritardo. Dico che a ciascuno la propria e una regola non possono mai dettare nulla in questo settore.

Scrivere una funzione sleep è semplice e reso ancora più utilizzabile con le promesse JavaScript:

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

// Usage!
sleep(500).then(() => {
    // Do something after the sleep!
});

190
A titolo di chiusura. function foobar(el) { setTimeout(function() { foobar_cont(el); }, 5000); }
caos

68
ok, e cosa succede se il codice non è destinato a essere utilizzato in una pagina Web?
Eugenio Miró,

10
@ EugenioMiró se il codice non è destinato a essere utilizzato in una pagina Web, fare in modo che il modello a oggetti dell'host implementi un metodo sleep. - Penso che la domanda sia orientata verso il DOM che è esposto a javascript in esecuzione su pagine Web.
BrainSlugs83

31
@Nosredna sì, capiamo come effettuare chiamate asincrone, questo non ci aiuta a dormire (). Voglio che le mie chiamate vengano effettuate in un determinato ordine e che i dati vengano ripristinati in un determinato ordine. Sono profondo 5 livelli in un ciclo for. Voglio BLOCCARE l'esecuzione. Un vero metodo di sospensione non "rallenta il browser", il controllo delle mani di sospensione torna al browser e a tutti gli altri thread che richiedono tempo alla CPU mentre è ancora bloccato.
BrainSlugs83

382
questa non è una risposta alla domanda.
TMS

303

Solo per debug / dev , inserisco questo se è utile a qualcuno

Roba interessante, in Firebug (e probabilmente altre console js), non succede nulla dopo aver premuto invio, solo dopo la durata del sonno specificata (...)

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

Esempio di utilizzo:

function sleepThenAct(){ sleepFor(2000); console.log("hello js sleep !"); }

36
Questa non è una risposta È esattamente lo stesso del codice nella domanda, tranne leggermente più breve.
jab

16
Sei impegnato ad aspettare, davvero? In JS? Per secondi? Se vedo un sito Web in questo modo, verrà bloccato.
mafu,

35
@mafu Ecco perché dice only for debug/dev... rolleyes
xDaizu,

12
NON FARE MAI QUESTO. Questo farà sì che la CPU raggiunga il 100% sul core che esegue e lo bloccherà.
noego,

3
Questo è utile, e forse l'unico modo per dormire, all'interno di un'applicazione javascript da riga di comando, perché async / wait non è utile.
Wheezil,

177

Concordo con gli altri poster, un sonno intenso è solo una cattiva idea.

Tuttavia, setTimeout non regge l'esecuzione, esegue la riga successiva della funzione immediatamente dopo che il timeout è impostato, non dopo che il timeout è scaduto, in modo che non compia la stessa attività che un sonno compirebbe.

Il modo per farlo è suddividere la funzione in parti prima e dopo.

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

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

Assicurati che i nomi delle tue funzioni descrivano ancora accuratamente cosa sta facendo ogni pezzo (IE GatherInputThenWait e CheckInput, piuttosto che funcPart1 e funcPart2)

modificare

Questo metodo ha lo scopo di non eseguire le righe di codice che decidi fino a DOPO il timeout, pur restituendo il controllo al PC client per eseguire qualsiasi altra cosa in coda.

Ulteriore modifica

Come sottolineato nei commenti, NON funzionerà assolutamente in un ciclo. Potresti fare un po 'di brutto (brutto) hacking per farlo funzionare in un ciclo, ma in generale sarà solo un disastroso codice di spaghetti.


12
Si. Dove questo diventa complicato è quando hai un loop o anche un loop nidificato. Devi abbandonare il tuo per i loop e avere invece i contatori.
Nosredna,

Touché. Voglio dire, sarebbe ancora possibile, ma brutto e hacker in quel caso. Potresti anche usare alcune variabili statiche booleane di stato, ma è anche abbastanza hacker.
DevinB,

2
-1 per questo. Ancora una volta, questo non risponde alla domanda. Questa è più una risposta a una domanda come "Come eseguire una funzione in modo asincrono" che è molto diversa da "Come bloccare un'esecuzione di codice".
Deepak GM,

6
@Nosredna No, useresti una chiusura. Ad esempio: function foo(index) { setTimeout(function() { foo_continue(index); }, 10000); }e for(var X = 0; X < 3;X++) { foo(X); }- viene passato il valore di X foo, che viene poi riutilizzato sotto il nome indexquando foo_continueviene infine chiamato.
Izkata,

2
@Alexander Naturalmente, perché il punto di setTimeout () è impedire il blocco del browser eseguendo il codice in modo asincrono. Inserisci l' console.log()interno foo_continue()nella versione setTimeout e otterrai lo stesso risultato.
Izkata,

132

Per amore di $ DEITY, ti preghiamo di non creare una funzione sleep in attesa. setTimeoute setIntervalfai tutto il necessario.

var showHide = document.getElementById('showHide');
setInterval(() => {
    showHide.style.visibility = "initial";
    setTimeout(() => {
        showHide.style.visibility = "hidden"
    }, 1000);
    ;
}, 2000);   
<div id="showHide">Hello! Goodbye!</div>

Ogni due secondi di intervallo nasconde il testo per un secondo. Questo mostra come usare setInterval e setTimeout per mostrare e nascondere il testo ogni secondo.


3
Beh, non proprio tutto: setInterval dà un'impressione molto migliore del polling.
annakata,

3
Che cosa sarebbe quel pezzo di codice non trattenere nel motore JavaScript?
Deniz Dogan,

10
A meno che non sia necessario che il sonno sia sincrono, nel qual caso questa è una domanda completamente valida.
Aaron Dufour,

36
Penso che molti di noi potrebbero dimenticare che JavaScript non è una lingua solo per browser. Questo tipo potrebbe creare un'utilità da riga di comando Nodo che richiede una breve pausa senza la necessità di affrontare tutti i problemi relativi all'ambito variabile forniti con setTimeout.
Phil LaNasa,

3
@PhilLaNasa: se la chiusura sintattica fa ancora paura, bisogna seriamente allacciarsi e lavorare attraverso il Nodo 101.
caos

113

So che questa è una domanda un po 'vecchia, ma se (come me) stai usando Javascript con Rhino, puoi usare ...

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.
   */
}

4
È una chiamata a Java?
Ken Sharp,

14
Questo è Java non Javascript
RousseauAlexandre

18
@RousseauAlexandre errato. È JavaScript usando Rhino (al momento, potrebbe essere ugualmente Nashorn in questi giorni)
mjaggard

71

Se stai usando jQuery, qualcuno ha effettivamente creato un plug-in "delay" che non è altro che un wrapper per 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;
};

È quindi possibile utilizzarlo in una riga di chiamate di funzione come previsto:

$('#warning')
.addClass('highlight')
.delay(1000)
.removeClass('highlight');

4
Questa non è una cattiva soluzione. Mantiene il contesto e la catenabilità.
Nosredna,

39
A partire da jQuery 1.4, .delay()fa parte di jQuery (sebbene con semantica diversa dall'implementazione di cui sopra). api.jquery.com/delay
Matt Ball

7
Ciò che sicuramente mancava a questa domanda era una risposta jQuery . Sono contento di averlo ottenuto!
xDaizu,

1
Se è necessario un ritardo tra due chiamate indipendenti, sì. Se hai bisogno di ritardi per rallentare un loop, no.
Galles,

46

Ho cercato anche la soluzione sleep (non per il codice di produzione, solo per dev / test) e ho trovato questo articolo:

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

... ed ecco un altro link con soluzioni lato client: http://www.devcheater.com/

Inoltre, quando chiami alert(), anche il tuo codice verrà messo in pausa, mentre viene mostrato l'avviso: devi trovare un modo per non visualizzare l'avviso ma ottenere lo stesso effetto. :)


35
Sono d'accordo, molte persone stanno dicendo: "No, non farlo nel codice di produzione!" Sì, non voglio. Voglio farlo nel codice di prova usa e getta, e di conseguenza non voglio passare molto tempo a creare una soluzione elegante.
user435779,

31

Ecco una semplice soluzione che utilizza un XMLHttpRequest sincrono:

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

contenuto di sleep.php:

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

Ora chiamalo con: sleep (5);


5
@lukad, Usa setTimeout()se funziona, ma se farlo significa svelare 1000 righe di callback questo potrebbe iniziare a non sembrare uno scherzo.
pguardiario,

11
Approccio unico, anche se purtroppo XMLHttpRequests non asincrono sono deprecati e verranno rimossi in futuro. Il che è divertente, perché questo fatto è ciò che mi ha portato a questa domanda in primo luogo.
Beejor,

Questa in realtà è una buona idea IMO. Anche se non credo che l'API di sospensione (URL richiesta) debba essere pubblica in quanto può essere abusata.
Vahid Amiri,

@Beejor pensare sempre solo al futuro significa vivere
sull'irrealtà

bello ma sai se a volte Internet è lento o il tempo di ping del sito Web è alto di quanto dormirà script per più di tempo di discussione. Come se si utilizza sleep(300)e il sito Web impiega tempo 150 ms per la risposta rispetto al codice javascript sarà inattivo per 450 ms. e se la connessione Internet viene persa dal browser funzionerà per soli 0ms. Quindi non è una soluzione migliore
H Chauhan

30

Ecco qui. Come dice il codice, non essere un cattivo sviluppatore e usalo sui siti web. È una funzione di utilità di sviluppo.

// 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) {}
}

17
È praticamente la stessa cosa dell'OP.
Andrew Barber,

5
Per essere più precisi, è ciò a cui OP ha chiesto un ALTERNATIVO.
Galles,

La soluzione non è buona, ma in alcuni punti async/awaitnon è purtroppo reattiva e dobbiamo usarla obbligatoriamente.
Nabi KAZ,

21

Personalmente mi piace il semplice:

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

poi:

sleep(2); // Sleeps for 2 seconds

Lo sto usando tutto il tempo per creare un tempo di caricamento falso durante la creazione di script in P5js


3
Vedo questa come la versione più ottimizzata della domanda principale: non fa alcun calcolo matematico all'interno del loop, solo un semplice confronto. È un po 'difficile da leggere.
Egez,

4
MAI FARE MAI QUELLO. Hai controllato l'utilizzo della CPU mentre questa funzione è attiva? Dovrebbe essere vicino al 100% se gli dai abbastanza tempo.
noego

2
@hegez: dato che il loop verrà eseguito per un periodo di tempo fisso a parete, non importa quale sia, sembra che l'ottimizzazione del loop sia in qualche modo accanto al punto.
ShadowRanger il

@noego In che modo? Ho appena testato nel nodo 10, non ho alcuna modifica all'utilizzo della CPU
melMass

@melMass Questa funzione blocca il thread del nodo per n secondi mantenendo occupata la CPU al 100%. Questa "soluzione" è una pessima idea per questi due motivi (blocco + CPU killer). L'attesa DEVE essere non bloccante, quindi asincrona.
Jeremy Thille,

20

Primo:

Definire una funzione che si desidera eseguire in questo modo:

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

Quindi pianificare la sua esecuzione con il metodo setTimeout:

setTimeout(alertWorld,1000)

Nota due cose

  • il secondo argomento è il tempo in millisecondi
  • come primo argomento devi passare solo il nome (riferimento) della funzione, senza la parentesi


18

Una soluzione migliore per far apparire le cose come la maggior parte delle persone è utilizzare una funzione anonima:

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

Questo è probabilmente il più vicino a qualcosa che fa semplicemente quello che vuoi.

Nota, se hai bisogno di più di un sonno, questo può diventare brutto in fretta e potrebbe essere necessario ripensare il tuo design.


questo è quello che ha funzionato per me su browser desktop e un telefono cellulare più vecchio. Gli altri che ho provato non hanno funzionato su tutti.
Mike,

10

Per i browser, sono d'accordo che setTimeout e setInterval sono la strada da percorrere.

Ma per il codice lato server, potrebbe essere necessaria una funzione di blocco (ad esempio, quindi è possibile avere effettivamente la sincronizzazione dei thread).

Se stai usando node.js e meteor, potresti aver incontrato i limiti dell'uso di setTimeout in una fibra. Ecco il codice per la sospensione lato server.

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');

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


Server may require a blocking function... Non vedo come bloccare con forza l'unico thread di Node e rendere il tuo intero server non rispondente per diversi secondi sia una buona idea, ma qualunque cosa
Jeremy Thille,

10

Incapsulerei setTimeOut in una promessa per la coerenza del codice con altre attività asincrone: Demo in Fiddle

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

Usato così:

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

È facile ricordare la sintassi se si utilizzava Promises.


4
Perché è meglio che usare semplicemente setTimeout (function () {/ * do qualcosa * /}, 2000) ;?
JSideris

10

Aggiornamento 2019 tramite Atomics.wait

Dovrebbe funzionare nel Nodo 9.3 o successivo.

Avevo bisogno di un timer abbastanza preciso in Node.js e funziona benissimo per questo. Tuttavia sembra che ci sia un supporto estremamente limitato nei browser.

let ms = 10000;
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);

Ha funzionato alcuni benchmark di 10 secondi.

Con setTimeout ricevo un errore fino a 7000 microsecondi. (7ms)

Con Atomics il mio errore sembra rimanere sotto i 600 microsecondi. (0.6ms)

Aggiornamento 2020: in sintesi

function sleep(millis){ // need help of a server-side page
  let netMillis=Math.max(millis-5,0); //assuming 5ms overhead
  let xhr=new XMLHttpRequest();
  xhr.open('GET','/sleep.jsp?millis='+netMillis+'&rand='+Math.random(), false);
  try{
    xhr.send();
  }catch(e){
  }
}
function sleepAsync(millis){ // use only in async function
  let netMillis=Math.max(millis-1,0); // assuming 1ms overhead
  return new Promise((resolve)=>{
    setTimeout(resolve, netMillis);
  });
}
function sleepSync(millis){ // use only in worker thread, currently Chrome-only
  Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, millis);
}

function sleepTest(){
  console.time('sleep');
  sleep(1000);
  console.timeEnd('sleep');
}
async function sleepAsyncTest(){
  console.time('sleepAsync');
  await sleepAsync(1000);
  console.timeEnd('sleepAsync');
}
function sleepSyncTest(){ 
  let source=`${sleepSync.toString()}
    console.time('sleepSync');
    sleepSync(1000);
    console.timeEnd('sleepSync');`;
  let src='data:text/javascript,'+encodeURIComponent(source);
  console.log(src);
  var worker=new Worker(src);
}

di cui sleep.jspappare una pagina lato server, ad esempio

<%
try{
  Thread.sleep(Long.parseLong(request.getParameter("millis")));
}catch(InterruptedException e){}
%>

A mio avviso migliore della soluzione accettata che non può essere implementata come una semplice funzione senza asincronizzazione / attesa nel chiamante.
GroovyDotCom

sì, finché sei consapevole che questo sta bloccando e che di solito non è una buona cosa
Kapytanhook,

Abbastanza bello, ma il fatto che questo sia davvero supportato solo in Chrome e Firefox non lo rende molto praticabile per gli usi sul web. (Nov 2019)
JGreatorex

9

La maggior parte delle risposte qui sono errate o per lo meno obsolete. Non c'è motivo per cui javascript debba essere a thread singolo, e in effetti non lo è. Oggi tutti i principali browser supportano i lavoratori, prima ancora che questo fosse il caso di altri runtime javascript come Rhino e Node.js che supportavano il multithreading.

"Javascript è a thread singolo" non è una risposta valida. Ad esempio, l'esecuzione di una funzione sleep all'interno di un lavoratore non bloccherebbe alcun codice in esecuzione nel thread dell'interfaccia utente.

Nei runtime più recenti che supportano generatori e rendimento, si potrebbe apportare funzionalità simili alla funzione sleep in un singolo ambiente thread:

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

Questa imitazione del sonno è diversa da una vera funzione sleep in quanto non blocca il thread. È semplicemente zucchero in aggiunta all'attuale funzione setTimeout di javascript. Questo tipo di funzionalità è stato implementato in Task.js e dovrebbe funzionare oggi su Firefox.


I lavoratori non sono implementati in IE, almeno attraverso la versione 10. Che attualmente rappresenta un gran numero di utenti.
Beejor,

È vero, e anche allora non è pratico implementare sleeputilizzando più lavoratori. Se si utilizzano le funzioni del generatore Node.js sono già implementate e possono essere utilizzate come descritto. I browser mainstream non hanno implementato tutti i generatori ad oggi.
Gabriel Ratener,

8

Ho cercato / cercato su google alcune pagine web su javascript sleep / wait ... e non c'è alcuna risposta se vuoi che javascript sia "RUN, DELAY, RUN" ... quello che la maggior parte delle persone è stato è "RUN, RUN (inutile roba), RUN "o" RUN, RUN + RUN ritardato "....

Quindi ho mangiato degli hamburger e ho pensato ::: ecco una soluzione che funziona ... ma devi tagliare i tuoi codici di marcia ... ::: sì, lo so, questo è solo un refactoring di facile lettura .. ancora ...

//......................................... //Esempio 1:

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

// .................................... // esempio2:

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

// ................. esempio3:

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

// .............. esempio4:

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

5
Ok, funziona con setTimeput, ma è difficile vedere cosa sta succedendo. L'uso di setTimeout stesso è più semplice di così.
naugtur,

7
function sleep(milliseconds) {
  var start = new Date().getTime();
  for (var i = 0; i < 1e7; i++) {
    if ((new Date().getTime() - start) > milliseconds){
      break;
    }
  }
}

È la stessa della vera domanda. Non ha molto senso renderlo la vera risposta.
EML

2
Non è una buona soluzione: l'utilizzo di questo in JavaScriptExecutor di Selenium blocca il mio browser Chrome circa il 50% delle volte su un MacBook Pro 2104.
smeriglio

7

La soluzione più breve senza dipendenze:

await new Promise(resolve => setTimeout(resolve, 5000));

Non funziona in IE11. Viene visualizzato un errore di sintassi per la funzione freccia.
DDphp,

@ Uso Java-DKawait new Promise(function(resolve) { setTimeout(resolve, 5000); });
k06a

6

Non puoi dormire così in JavaScript, o meglio, non dovresti. L'esecuzione di una sospensione o di un ciclo while causerà il blocco del browser dell'utente fino al termine del ciclo.

Utilizzare un timer, come specificato nel collegamento a cui si fa riferimento.


6

Uno scenario in cui potresti desiderare una funzione sleep () anziché utilizzare setTimeout () è se hai una funzione che risponde a un clic dell'utente che finirà per aprire una nuova finestra popup e hai avviato un'elaborazione che richiede un breve periodo per completare prima che venga visualizzato il popup. Spostare la finestra aperta in una chiusura significa che generalmente viene bloccata dal browser.


6

Riesco a capire lo scopo di una funzione sleep se devi occuparti dell'esecuzione sincrona. Le funzioni setInterval e setTimeout creano un thread di esecuzione parallelo che restituisce la sequenza di esecuzione al programma principale, che è inefficace se si deve attendere un determinato risultato. Naturalmente si possono usare eventi e gestori, ma in alcuni casi non è quello che si intende.


6

Aggiungendo i miei due bit. Avevo bisogno di un'attesa impegnativa per scopi di test. Non volevo dividere il codice in quanto sarebbe stato un sacco di lavoro, quindi è stato semplice farlo per me.

for (var i=0;i<1000000;i++){                    
     //waiting
  }

Non vedo alcun aspetto negativo nel fare questo e ha fatto il trucco per me.


Potrebbe essere compilato.
Viktor Sehr

Per favore, non farlo in questo modo. Questa è una chiamata di blocco del sonno, il che significa che nessun altro javascript può essere eseguito mentre il tuo codice registra il thread JS.
Steve Midgley,

5
@SteveMidgley "nessun altro javascript [in grado di eseguire] mentre il tuo codice registra il thread JS" mi sembra esattamente ciò che l'OP vuole fare ¯_ (ツ) _ / ¯
drigoangelo

1
Ho appena eseguito alcuni test e sembra che anche un loop vuoto blocchi il browser e la CPU (non solo JavaScript). E l'utilizzo dei forloop verrà quasi sempre eseguito immediatamente, indipendentemente dal valore massimo per ie anche con un codice matematico complesso inserito all'interno. Quindi, a meno che tu non stia aspettando solo pochi millisecondi, sembra che non ci sia ancora modo di dormire con grazia in JS.
Beejor,

1 milione è troppo grande. Per me abbastanza 10k
Vlad

6

Può essere fatto usando il metodo sleep di Java. L'ho testato in FF e IE e non blocca il computer, mastica risorse o non provoca hit senza fine sul server. Sembra una soluzione pulita per me.

Per prima cosa devi caricare Java sulla pagina e renderne disponibili i metodi. Per farlo, ho fatto questo:

<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" />

Quindi, tutto ciò che devi fare quando vuoi una pausa indolore nel tuo JS è:

java.lang.Thread.sleep(xxx)

Dove xxx è il tempo in millisecondi. Nel mio caso (a titolo di giustificazione), questo faceva parte dell'esecuzione degli ordini di back-end in una società molto piccola e avevo bisogno di stampare una fattura che doveva essere caricata dal server. L'ho fatto caricando la fattura (come pagina Web) in un iFrame e quindi stampando l'iFrame. Ovviamente, ho dovuto aspettare fino a quando la pagina non fosse stata caricata completamente prima di poter stampare, quindi JS ha dovuto mettere in pausa. Ho realizzato questo facendo cambiare la pagina della fattura (nell'iFrame) un campo modulo nascosto nella pagina padre con l'evento onLoad. E il codice sulla pagina principale per stampare la fattura sembrava così (parti irrilevanti tagliate per chiarezza):

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

Quindi l'utente preme il pulsante, lo script carica la pagina della fattura, quindi attende, controllando ogni quarto di secondo per vedere se il caricamento della pagina della fattura è terminato, quindi viene visualizzata la finestra di dialogo di stampa per l'utente per inviarlo alla stampante. QED.


12
Sembra un'anima piuttosto mostruosa quando si considera la cosa semplice che l'autore voleva ottenere.
Xaralis,

2
Ciò dipende dalle applet Java che sono obsolete.
Vahid Amiri,

6

Molte risposte non rispondono (direttamente) alla domanda, e nemmeno questa ...

Ecco i miei due centesimi (o funzioni):

Se vuoi funzioni meno ingombranti di setTimeoute setInterval, puoi avvolgerle in funzioni che invertono semplicemente l'ordine degli argomenti e danno loro dei bei nomi:

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

Versioni di CoffeeScript:

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

Puoi quindi usarli bene con funzioni anonime:

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

Ora si legge facilmente come "dopo N millisecondi, ..." (o "ogni N millisecondi, ...")


5

Per il caso specifico di voler spaziare una serie di chiamate eseguite da un ciclo, è possibile utilizzare qualcosa come il codice qui sotto con prototipo. Senza prototipo, è possibile sostituire la funzione di ritardo con 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)
}

5

Se sei su node.js, puoi dare un'occhiata alle fibre : un'estensione C nativa al nodo, una simulazione multi-threading.

Ti permette di fare un vero sleepin un modo che sta bloccando l'esecuzione in una fibra, ma non è bloccante nel thread principale e in altre fibre.

Ecco un esempio appena tratto dal loro 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');

- e i risultati sono:

$ 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)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.