Attendere 5 secondi prima di eseguire la riga successiva


313

Questa funzione di seguito non funziona come voglio io; essendo un novizio JS non riesco a capire perché.

Ho bisogno di aspettare 5 secondi prima di verificare se lo newStateè -1.

Attualmente, non aspetta, controlla solo subito.

function stateChange(newState) {
  setTimeout('', 5000);

  if(newState == -1) {
    alert('VIDEO HAS STOPPED');
  }
}

Risposte:


323

Devi inserire il tuo codice nella funzione di callback che fornisci a setTimeout:

function stateChange(newState) {
    setTimeout(function () {
        if (newState == -1) {
            alert('VIDEO HAS STOPPED');
        }
    }, 5000);
}

Qualsiasi altro codice verrà eseguito immediatamente.


4
Il problema principale è che in alcuni casi (in particolare test) questo è dolorosamente inadeguato. Cosa succede se è necessario dormire per 500 ms prima di tornare dalla funzione, ad esempio per simulare una richiesta http asincrona lenta ?
A.Grandt,

14
Se per "test" intendi test unitari: il tuo framework di test dovrebbe avere un modo per eseguire test asincroni. Se intendi test manuali: la scheda Rete di Chrome ha un menu a discesa Limitazione per simulare le richieste lente.
Joseph Silber,

1
cosa succede se sviluppo un'estensione di Chrome e l'ultimo valore valutato nello script iniettato dovrebbe darmi il risultato; e ho bisogno di alcuni ritardi?
Mirek,

184

Non dovresti davvero farlo , l'uso corretto del timeout è lo strumento giusto per il problema del PO e ogni altra occasione in cui vuoi semplicemente eseguire qualcosa dopo un periodo di tempo. Joseph Silber lo ha dimostrato bene nella sua risposta. Tuttavia, se in alcuni casi di non produzione vuoi davvero appendere il thread principale per un periodo di tempo, lo farà.

function wait(ms){
   var start = new Date().getTime();
   var end = start;
   while(end < start + ms) {
     end = new Date().getTime();
  }
}

Con esecuzione nel modulo:

console.log('before');
wait(7000);  //7 seconds in milliseconds
console.log('after');

Sono arrivato qui perché stavo costruendo un semplice test case per sequenziare un mix di operazioni asincrone attorno a operazioni di blocco di lunga durata (ovvero costose manipolazioni DOM) e questa è la mia operazione di blocco simulato. Si adatta bene a quel lavoro, quindi ho pensato di pubblicarlo per chiunque arrivi qui con un caso d'uso simile. Anche così, sta creando un oggetto Date () in un ciclo while, che potrebbe molto travolgere il GC se funziona abbastanza a lungo. Ma non posso sottolineare abbastanza, questo è adatto solo per i test, per costruire qualsiasi funzionalità reale che dovresti fare riferimento alla risposta di Joseph Silber.


7
Questo non fermerà l'esecuzione di JavaScript.
Terry Lin,

23
@TerryLin Prova a eseguirlo.
Mic

6
Quindi sostanzialmente stai sprecando tempo CPU. Non è un'attesa perché non stai mettendo il thread in modalità di sospensione, consentendo al processore principale di concentrarsi su altre attività.
Kyordhel,

6
@Gzork Thread sleep è solo un modo per implementare una funzione di attesa, e sfortunatamente non è disponibile nel contesto del javascript lato client. Tuttavia, se stai pensando che altre attività asincrone nel client saranno completate mentre è in esecuzione, allora ovviamente non l'hai testato. Anche se lo userei nel thread principale, ho messo insieme un violino che illustra come anche se questo viene chiamato tramite setTimeout in primo luogo, interrompe comunque altri eventi asincroni jsfiddle.net/souv51v3/1 - troverai anche il La finestra JSFiddle stessa non risponde mentre viene completata.
Mic

1
Soluzione terribile IMHO - maiali CPU mentre è "inattivo". Il modo giusto di dormire è via asincrono / attendi questa risposta stackoverflow.com/questions/951021/… o Etienne's.
David Simic,

163

Ecco una soluzione che utilizza la nuova sintassi async / await .

Assicurati di controllare il supporto del browser in quanto questa è una nuova funzionalità introdotta con ECMAScript 6.

Funzione utile:

const delay = ms => new Promise(res => setTimeout(res, ms));

Uso:

const yourFunction = async () => {
  await delay(5000);
  console.log("Waited 5s");

  await delay(5000);
  console.log("Waited an additional 5s");
};

Il vantaggio di questo approccio è che rende il codice simile e si comporta come un codice sincrono.


Non è necessario ECMAScript 6: se si stanno già utilizzando le promesse per eseguire il caricamento asincrono e si desidera solo imitare una parte della catena per molto tempo, è possibile aggiungere questa funzione wait () alla catena.
Dovev Hefetz,

2
Questa è davvero la risposta migliore con la nuova sintassi. Ho avuto problemi con l'utilizzo della soluzione wait () sopra.
pianoman102


36

Non dovresti semplicemente provare a mettere in pausa 5 secondi in JavaScript. Non funziona così. È possibile pianificare una funzione di codice per l'esecuzione tra 5 secondi da ora, ma è necessario inserire il codice che si desidera eseguire in seguito in una funzione e il resto del codice dopo tale funzione continuerà a essere eseguito immediatamente.

Per esempio:

function stateChange(newState) {
    setTimeout(function(){
        if(newState == -1){alert('VIDEO HAS STOPPED');}
    }, 5000);
}

Ma se hai un codice come questo:

stateChange(-1);
console.log("Hello");

L' console.log()istruzione verrà eseguita immediatamente. Non attenderà fino a quando il timeout non scatta nella stateChange()funzione. Non puoi semplicemente mettere in pausa l'esecuzione di JavaScript per un periodo di tempo predeterminato.

Invece, qualsiasi codice che si desidera eseguire ritardi deve essere all'interno della setTimeout()funzione di callback (o chiamato da quella funzione).

Se si provasse a "mettere in pausa" il ciclo, in sostanza si "appendere" l'interprete Javascript per un periodo di tempo. Poiché Javascript esegue il codice in un solo thread, quando si esegue il ciclo continuo non è possibile eseguire nient'altro (nessun altro gestore di eventi può essere chiamato). Quindi, il ciclo in attesa di una variabile da cambiare non funzionerà mai perché nessun altro codice può essere eseguito per cambiare quella variabile.


31
Non puoi semplicemente mettere in pausa l'esecuzione di JavaScript per un periodo di tempo predeterminato . Penso che intendi che non dovresti, dato che puoi (se vuoi impiccarti):var t = new Date().getTime(); while (new Date().getTime() < t + millisecondsToLockupBrowser);
Joseph Silber

9
@JosephSilber - OK, potresti farlo, ma in pratica non funziona poiché molti browser apriranno una finestra di dialogo dicendo che uno script non ha risposto ED è un'esperienza utente orribile ed è un male per la durata della batteria e la pagina è appeso mentre lo faceva e ... Sarebbe male.
jfriend00

12
Beh, ovviamente sarebbe orribile, e nessuno dovrebbe mai e poi mai e poi mai farlo. Non riuscivo proprio a resistere al mio "bene" interiore . Scusate.
Joseph Silber,

31

Se sei in una funzione asincrona puoi semplicemente farlo in una riga:

console.log(1);
await new Promise(resolve => setTimeout(resolve, 3000)); // 3 sec
console.log(2);

Nota , se la destinazione è NodeJS, sarà più efficiente utilizzarla (è una funzione setTimeout promessa predefinita):

await setTimeout[Object.getOwnPropertySymbols(setTimeout)[0]](3000) // 3 sec

Qual è la differenza tra le due implementazioni?
EAzevedo

1
Attualmente, non c'è differenza. Ma se ad un certo punto il nodo deciderà di renderlo più veloce / più sicuro / più efficiente, utilizzerai la versione js del nodo in anticipo. Sebbene la leggibilità sia più probabile che sia il fattore chiave per la maggior parte delle persone, nel qual caso è meglio usare il primo modo.
Shl

Grazie. La tua risposta ha risolto un problema che ho già affrontato per tre giorni. Grazie.
EAzevedo

8

Prova questo:

//the code will execute in 1 3 5 7 9 seconds later
function exec() {
    for(var i=0;i<5;i++) {
        setTimeout(function() {
            console.log(new Date());   //It's you code
        },(i+i+1)*1000);
    }
}

7

Il modo migliore per creare una funzione come questa per attendere in milli secondi, questa funzione attenderà i millisecondi forniti nell'argomento:

function waitSeconds(iMilliSeconds) {
    var counter= 0
        , start = new Date().getTime()
        , end = 0;
    while (counter < iMilliSeconds) {
        end = new Date().getTime();
        counter = end - start;
    }
}


3

Basato sulla risposta di Joseph Silber , lo farei così, un po 'più generico.

Avresti la tua funzione (ne creiamo una in base alla domanda):

function videoStopped(newState){
   if (newState == -1) {
       alert('VIDEO HAS STOPPED');
   }
}

E potresti avere una funzione di attesa:

function wait(milliseconds, foo, arg){
    setTimeout(function () {
        foo(arg); // will be executed after the specified time
    }, milliseconds);
}

Alla fine avresti:

wait(5000, videoStopped, newState);

Questa è una soluzione, preferirei non usare argomenti nella funzione wait (avere solo foo();invece di foo(arg);) ma questo è per l'esempio.



1

Puoi aggiungere ritardo apportando piccole modifiche alla tua funzione (asincronizza e attendi).

const add5SecondsDelay = () => {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve('5 seconds');
    }, 50000);
  });
}

async function asyncFunctionCall() {

  console.log("stpe-1"); 
  const result = await add5SecondsDelay ();
  console.log("step-2 after 5 seconds delay"); 

}

asyncFunctionCall();

-2

usando angularjs:

$timeout(function(){
if(yourvariable===-1){
doSomeThingAfter5Seconds();
}
},5000)

-2

Crea una nuova funzione Js

function sleep(delay) {
        var start = new Date().getTime();
        while (new Date().getTime() < start + delay);
      }

Chiamare la funzione quando si desidera ritardare l'esecuzione. Usa millisecondi in int per il valore di ritardo.

####Some code
 sleep(1000);
####Next line

3
Ciò consumerà troppe risorse.
awavi,

-2

L'ho usato per eseguire giochi per PC da Edge o IE. E si chiude IE Edge dopo 7 secondi.

Firefox e Google Chrome non possono essere utilizzati per avviare i giochi in questo modo.

<html<body>
<a href="E:\game\game.exe" name="game" onmouseout="waitclose(7000);"> game
<img src="game.jpg" width="100%" height="97%" ></a>
<script>
function waitclose(ms){
 var start = new Date().getTime();var end=start;
 while(end < start + ms) {end = new Date().getTime();}
window.open('', '_self', ''); window.close();
}
</script>
</body></html>
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.