Eseguire lo script dopo un ritardo specifico utilizzando JavaScript


189

Esiste un metodo JavaScript simile a jQuery delay()o wait()(per ritardare l'esecuzione di uno script per un determinato periodo di tempo)?

Risposte:


189

C'è il seguente:

setTimeout(function, milliseconds);

funzione che può essere passata il tempo dopo il quale verrà eseguita la funzione.

Vedi: Metodo finestrasetTimeout() .


3
Non è un'espressione che viene eseguita, è una funzione. La risposta di @Marius lo dimostra.
pedrofurla,

117
questo non è un ritardo, è un fork. Il ritardo dovrebbe funzionare nello stesso thread.
DragonLord,

13
Questo eseguirà immediatamente function_reference. Per "lavorare" (in modo asincrono) dovrebbe essere indicato come: setTimeout (function () {MethodToCall ();}, 1000);
Bernoulli IT

6
Voglio sottolineare che stiamo parlando di JavaScript; far apparire "thread" o che dovrebbe funzionare "in modo sincrono" può essere vero tecnicamente e semanticamente ma non si adatta davvero al contesto di JavaScript, considerando che non c'è davvero alcun modo per ottenere un ritardo con uno di questi metodi (non t crea "discussioni" in JS come in altre lingue). Inoltre, questo non verrà eseguito immediatamente a function_referencemeno che non lo includa (). Cioè function_referenceè proprio questo: un riferimento; il passaggio function_reference()invocherebbe immediatamente la funzione.
Danny Bullis,

237

Solo per aggiungere ciò che hanno detto tutti gli altri setTimeout: Se in futuro si desidera chiamare una funzione con un parametro, è necessario impostare alcune chiamate di funzione anonime.

È necessario passare la funzione come argomento per poterla chiamare in seguito. In effetti questo significa senza parentesi dietro il nome. Quanto segue chiamerà l'avviso immediatamente e visualizzerà "Hello world":

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

Per risolvere questo problema, puoi inserire il nome di una funzione (come ha fatto Flubba) oppure puoi utilizzare una funzione anonima. Se è necessario passare un parametro, è necessario utilizzare una funzione anonima.

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

Ma se esegui quel codice, noterai che dopo 2 secondi il popup mostrerà 'Hello Stack Overflow'. Questo perché il valore della variabile a è cambiato in questi due secondi. Per dirlo "Hello world" dopo due secondi, devi utilizzare il seguente frammento di codice:

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

Aspetterà 2 secondi e poi apparirà il popup "Ciao mondo".


37

Solo per espandere un po '... Puoi eseguire il codice direttamente nella setTimeoutchiamata, ma come dice @patrick , normalmente assegni una funzione di callback, come questa. Il tempo è millisecondi

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

27

Se vuoi davvero avere una funzione di blocco (sincrono) delay(per qualsiasi cosa), perché non fare qualcosa del genere:

<script type="text/javascript">
    function delay(ms) {
        var cur_d = new Date();
        var cur_ticks = cur_d.getTime();
        var ms_passed = 0;
        while(ms_passed < ms) {
            var d = new Date();  // Possible memory leak?
            var ticks = d.getTime();
            ms_passed = ticks - cur_ticks;
            // d = null;  // Prevent memory leak?
        }
    }

    alert("2 sec delay")
    delay(2000);
    alert("done ... 500 ms delay")
    delay(500);
    alert("done");
</script>

2
La difficoltà con questa soluzione è che utilizza attivamente un processore, il che porta a un maggiore consumo di energia e una diminuzione delle risorse disponibili per altri thread / processi (ad esempio altre schede, altri programmi). La sospensione, al contrario, sospende temporaneamente l'utilizzo da parte di un thread delle risorse di sistema.
ramcdougal,

1
meglio usare Date.now () invece di new Date () e non pensare alle perdite di memoria
WayFarer

1
Ovviamente richiede molta CPU, ma per test rapidi e sporchi funziona
Maris B.

Voglio una versione che non blocchi il thread, quindi posso aggiornare il DOM prima di delaying (per rispondere a questa domanda ). C'è un modo per farlo?
Gui Imamura,

3
Una routine più compatta: ritardo della funzione (ms) {var start_time = Date.now (); while (Date.now () - start_time <ms); }
Duca

15

Devi usare setTimeout e passargli una funzione di callback. Il motivo per cui non puoi usare la sospensione in javascript è perché nel frattempo impediresti a tutta la pagina di fare qualcosa. Non è un buon piano. Usa il modello di eventi di Javascript e resta felice. Non combatterlo!


2
Sarebbe comunque utile a scopo di test. Come ritardare l'invio di un modulo per alcuni secondi per valutare le modifiche alla pagina prima che venga effettuata una nuova richiesta HTTP.
rushinge,

1
@rushinge quindi imposta il callback per inviare il modulo e disabilitare il modulo predefinito submit
Populus

1
Pessima idea di lasciare un link come codice ... come ora non funziona.
Emmet Arries

1
O sai, potrei semplicemente aggiustarlo.
Patrick,

14

Puoi anche usare window.setInterval () per eseguire ripetutamente del codice a intervalli regolari.


2
setInterval () non dovrebbe essere usato invece dovrebbe usare setTimeout
paul

9
setTimeout()lo fa una volta, lo setInterval()fa ripetutamente. Se vuoi che il tuo codice venga eseguito ogni 5 secondi, setInterval()è fatto per il lavoro.
rcoup

11

Per aggiungere i commenti precedenti, vorrei dire quanto segue:

La setTimeout()funzione in JavaScript non mette in pausa l'esecuzione dello script di per sé, ma dice semplicemente al compilatore di eseguire il codice in futuro.

Non esiste una funzione che può effettivamente mettere in pausa l'esecuzione integrata in JavaScript. Tuttavia, puoi scrivere la tua funzione che fa qualcosa di simile a un ciclo incondizionato fino a quando non viene raggiunto il tempo utilizzando la Date()funzione e aggiungendo l'intervallo di tempo necessario.


11

Se hai solo bisogno di provare un ritardo puoi usare questo:

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

E poi se vuoi ritardare di 2 secondi, fai:

delay(2000);

Potrebbe non essere il migliore per la produzione però. Maggiori informazioni nei commenti


@ U2744 SNOWFLAKE Puoi provare ad essere un po 'più preciso nel tuo commento
Christoffer,

1
Bene, è un circuito affollato che scaricherà le batterie di laptop e altri dispositivi mobili e probabilmente impedirà anche all'interfaccia utente di rispondere (o persino visualizzare).
Ry-

@ U2744SNOWFLAKE Ha un senso. Ho aggiornato la risposta, per quello che ho usato questa funzione per :)
Christoffer il

2
Funziona abbastanza bene nello sviluppo per una soluzione rapida e sporca (e temporanea).
HumanInDisguise

5

perché non puoi mettere il codice dietro una promessa? (digitato dalla parte superiore della mia testa)

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


5

La semplice risposta è:

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

La funzione sopra attende 1 secondo (1000 ms) quindi imposta x su 1. Ovviamente questo è un esempio; puoi fare tutto ciò che vuoi all'interno della funzione anonima.


4

Mi è piaciuta molto la spiegazione di Maurius (la risposta più votata) con i tre diversi metodi di chiamata setTimeout.

Nel mio codice desidero navigare automaticamente alla pagina precedente al completamento di un evento di salvataggio AJAX. Il completamento dell'evento di salvataggio presenta una leggera animazione nel CSS che indica che il salvataggio ha avuto esito positivo.

Nel mio codice ho trovato una differenza tra i primi due esempi:

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

Questo non attende il timeout: il back () viene chiamato quasi immediatamente, indipendentemente dal numero inserito per il ritardo.

Tuttavia, cambiando questo in:

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

Questo fa esattamente quello che speravo.

Questo non è specifico dell'operazione back (), lo stesso accade con alert(). Fondamentalmente con quello alert()usato nel primo caso, il tempo di ritardo viene ignorato. Quando chiudo il popup, l'animazione per il CSS continua.

Pertanto, consiglierei il secondo o il terzo metodo che descrive anche se si utilizzano funzioni integrate e non si utilizzano argomenti.


1

Avevo alcuni comandi Ajax che volevo eseguire con un ritardo nel mezzo. Ecco un semplice esempio di un modo per farlo. Sono pronto a essere fatto a brandelli per il mio approccio non convenzionale. :)

//  Show current seconds and milliseconds
//  (I know there are other ways, I was aiming for minimal code
//  and fixed width.)
function secs()
{
    var s = Date.now() + ""; s = s.substr(s.length - 5);
  return s.substr(0, 2) + "." + s.substr(2);
}

//  Log we're loading
console.log("Loading: " + secs());

//  Create a list of commands to execute
var cmds = 
[
    function() { console.log("A: " + secs()); },
    function() { console.log("B: " + secs()); },
    function() { console.log("C: " + secs()); },
    function() { console.log("D: " + secs()); },
    function() { console.log("E: " + secs()); },
  function() { console.log("done: " + secs()); }
];

//  Run each command with a second delay in between
var ms = 1000;
cmds.forEach(function(cmd, i)
{
    setTimeout(cmd, ms * i);
});

// Log we've loaded (probably logged before first command)
console.log("Loaded: " + secs());

Puoi copiare il blocco di codice e incollarlo in una finestra della console e vedere qualcosa di simile:

Loading: 03.077
Loaded: 03.078
A: 03.079
B: 04.075
C: 05.075
D: 06.075
E: 07.076
done: 08.076

1

La soluzione più semplice per chiamare la funzione in ritardo è:

function executeWithDelay(anotherFunction) {
    setTimeout(anotherFunction, delayInMilliseconds);
}

0

funzione di ritardo:

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

utilizzo all'interno della asyncfunzione:

await delay(1000);

-1

Come altri hanno detto, setTimeout è la scommessa più sicura,
ma a volte non è possibile separare la logica in una nuova funzione, quindi è possibile utilizzare Date.now () per ottenere millisecondi e fare il ritardo da soli ....

function delay(milisecondDelay) {
   milisecondDelay += Date.now();
   while(Date.now() < milisecondDelay){}
}

alert('Ill be back in 5 sec after you click OK....');
delay(5000);
alert('# Im back # date:' +new Date());

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.