Computer finestre Internet

Timer in Javascript (setInterval, setTimeout). Esempi di funzione jQuery setTimeout () Javascript impedisce a più timer di eseguire setinterval contemporaneamente

Il timeout JavaScript è una funzione JavaScript nativa che esegue una parte di codice dopo un intervallo di tempo specificato (in millisecondi). Questo può tornare utile quando è necessario visualizzare un popup dopo che l'utente ha trascorso un po' di tempo sulla tua pagina. Oppure vuoi che l'effetto inizi quando passi il cursore su un elemento solo dopo un po' di tempo. In questo modo, puoi evitare l'attivazione involontaria dell'effetto se l'utente si sposta accidentalmente sopra.

Esempio semplice di setTimeout

Per dimostrare l'effetto di questa funzione, suggerisco di dare un'occhiata alla seguente demo, in cui viene visualizzata una finestra pop-up due secondi dopo aver fatto clic sul pulsante.

Visualizza demo

Sintassi

La documentazione MDN fornisce la seguente sintassi per setTimeout:

var timeoutID = window.setTimeout (func,); var timeoutID = window.setTimeout (codice,);

  • timeoutID è un id numerico che può essere utilizzato insieme a clearTimeout() per disabilitare il timer;
  • func è la funzione da eseguire;
  • codice ( in sintassi alternativa) - la riga di codice da eseguire;
  • ritardo - la durata del ritardo in millisecondi dopo il quale verrà eseguita la funzione. Il valore predefinito è 0.

setTimeout vs window.setTimeout

La sintassi sopra usa window.setTimeout. Come mai?

In effetti, setTimeout e window.setTimeout sono praticamente la stessa funzione. L'unica differenza è che nella seconda espressione utilizziamo il metodo setTimeout come proprietà dell'oggetto finestra globale.

Personalmente, penso che questo complichi solo molto il codice. Se dovessimo definire un metodo di timeout JavaScript alternativo che può essere trovato e restituito in ordine di priorità, incorreremmo in problemi ancora più grandi.

Per questo tutorial, non voglio pasticciare con l'oggetto finestra, ma in generale dipende da te quale sintassi usare.

Esempi di utilizzo

Questo potrebbe essere il nome della funzione:

funzione esplodere () (avviso ("Boom!");) setTimeout (esplodere, 2000);

Variabile che si riferisce alla funzione:

var esplodere = funzione () (avviso ("Boom!");); setTimeout (esplodere, 2000);

O una funzione anonima:

setTimeout (funzione () (avviso ("Boom!");), 2000);

  • Tale codice è mal percepito e, pertanto, sarà difficile da modernizzare o eseguire il debug;
  • Implica l'uso del metodo eval(), che potrebbe essere una potenziale vulnerabilità;
  • Questo metodo è più lento degli altri perché deve funzionare Interprete JavaScript.

Si noti inoltre che stiamo utilizzando il metodo di avviso per il timeout JavaScript per testare il codice.

Passaggio di parametri a setTimout

Nel primo ( inoltre, cross-browser), passiamo i parametri alla funzione di callback eseguita con setTimeout.

Nell'esempio seguente, estraiamo un saluto casuale dall'array dei saluti e lo passiamo come parametro alla funzione greet(), che viene eseguita da setTimeout con un ritardo di 1 secondo:

funzione salutare (saluto) (console.log (saluto);) funzione getRandom (arr) (return arr;) var saluti = ["Ciao", "Bonjour", "Tag Guten"], randomGreeting = getRandom (saluti); setTimeout (function () (greet (randomGreeting);), 1000);

Visualizza demo

Metodo alternativo

Nella sintassi all'inizio di questo articolo è presente un altro metodo che può essere utilizzato per passare i parametri alla funzione di callback eseguita dal timeout di JavaScript. Questo metodo implica l'output di tutti i parametri che seguono il ritardo.

Partendo dall'esempio precedente, otteniamo:

setTimeout (greet, 1000, randomGreeting);

Questo metodo non funzionerà in IE 9 e versioni precedenti, dove i parametri passati non sono definiti. Ma per risolvere questo problema su MDN ha un polyfill speciale.

Problemi correlati e "questo"

Il codice eseguito da setTimeout viene eseguito separatamente dalla funzione che lo ha chiamato. Per questo motivo, ci troviamo di fronte a determinati problemi, questa parola chiave può essere utilizzata come soluzione.

var persona = (firstName: "Jim", introduce: function () (console.log ("Ciao, io" m "+ this.firstName);)); persona.introduce (); // Output: Ciao, io" m Jim setTimeout (person.introduce, 50); // Output: Ciao, non sono definito

La ragione di questa conclusione risiede nel fatto che nel primo esempio questo porta all'oggetto person, e nel secondo esempio punta all'oggetto finestra globale, che non ha la proprietà firstName.

Per eliminare questa incoerenza, puoi utilizzare diversi metodi:

Forza questo per essere impostato

Questo può essere fatto usando bind(), un metodo che crea una nuova funzione che, quando chiamata come valore di this chiave, usa un valore specifico. Nel nostro caso, l'oggetto persona specificata. Questo ci dà come risultato:

setTimeout (person.introduce.bind (persona), 50);

Nota: il metodo bind è stato introdotto in ECMAScript 5, il che significa che funzionerà solo nei browser moderni. In altri, riceverai un errore di runtime quando lo applichi JavaScript "errore di timeout della funzione".

Usa la libreria

Molte librerie includono funzioni integrate necessarie per risolvere questo problema. Ad esempio, il metodo jQuery.proxy(). Prende una funzione e ne restituisce una nuova, in cui utilizzerà sempre un contesto specifico. Nel nostro caso il contesto sarà:

setTimeout ($. proxy (person.introduce, persona), 50);

Visualizza demo

Disabilita timer

Il valore restituito di setTimeout è un id numerico che può essere utilizzato per disabilitare il timer utilizzando la funzione clearTimeout():

var timer = setTimeout (myFunction, 3000); clearTimeout (timer);

Vediamolo in azione. Nel prossimo esempio, se clicchi sul pulsante " Inizia il conto alla rovescia”, Il conto alla rovescia inizia. Dopo che è finito, i gattini avranno il loro. Ma se premi il pulsante " Interrompi il conto alla rovescia", Il timeout JavaScript verrà interrotto e ripristinato.

Visualizza esempio

Riassumiamo

setTimeout è una funzione asincrona, il che significa che la chiamata ricevuta a questa funzione viene accodata e verrà eseguita solo dopo che tutte le altre azioni sullo stack sono state completate. Non può essere eseguito contemporaneamente ad altre funzioni oa un thread separato.

È estremamente importante capire come funzionano i timer JavaScript. Spesso il loro comportamento non corrisponde alla nostra percezione intuitiva del multithreading, e questo è dovuto al fatto che in realtà vengono eseguiti sullo stesso thread. Diamo un'occhiata a quattro funzioni con cui possiamo controllare i timer:

  • id var = setTimeout (fn, ritardo); - Crea un semplice timer che chiamerà la funzione specificata dopo il ritardo specificato. La funzione restituisce un ID univoco in base al quale il timer può essere messo in pausa.
  • id var = setInterval (fn, ritardo); - Simile a setTimeout, ma chiama continuamente la funzione all'intervallo specificato (fino all'arresto).
  • clearInterval (id);, clearTimeout (id); - Accetta un ID timer (restituito da una delle funzioni sopra descritte) e interrompe l'esecuzione del callback "a.
L'idea principale da considerare è che la precisione del periodo di ritardo del timer non è garantita. Per cominciare, il browser esegue tutti gli eventi JavaScript asincroni sullo stesso thread (come clic del mouse o timer) e solo quando l'evento è a sua volta. Ciò è meglio illustrato dal diagramma seguente:

Ci sono molte informazioni da comprendere in questa figura, ma comprenderle ti darà una comprensione più profonda di come funziona l'esecuzione asincrona di JavaScript. Questo diagramma rappresenta verticalmente il tempo in millisecondi e i blocchi blu rappresentano i blocchi di codice JavaScript che è stato eseguito. Ad esempio, il primo blocco viene eseguito in media in 18 ms, un clic del mouse blocca l'esecuzione per circa 11 ms, ecc.

JavaScript può eseguire solo un pezzo di codice (a causa della natura dell'esecuzione a thread singolo), ognuno dei quali blocca l'esecuzione di altri eventi asincroni. Ciò significa che quando si verifica un evento asincrono (come un clic del mouse, una chiamata timer o il completamento di una richiesta XMLHttp), viene aggiunto alla coda ed eseguito in seguito (l'implementazione, ovviamente, varia a seconda del browser, ma accettiamo di chiamarla "la coda")...

Per cominciare, immaginiamo che all'interno del blocco JavaScript inizino due timer: setTimeout con un ritardo di 10 ms e setInterval con lo stesso ritardo. A seconda di quando si avvia il timer, si attiverà nel momento in cui non abbiamo ancora completato il primo blocco di codice. Si noti, tuttavia, che non si attiva immediatamente (non possibile a causa del threading singolo). La funzione posticipata viene invece messa in coda ed eseguita alla successiva ora disponibile.

Inoltre, durante l'esecuzione del primo blocco JavaScript, si verifica un clic del mouse. Il gestore per questo evento asincrono (ed è asincrono, perché non possiamo prevederlo) non può essere eseguito direttamente in questo momento, quindi entra anche nella coda, come il timer.

Dopo che il primo blocco di codice JavaScript è stato eseguito, il browser pone la domanda "Cosa è in attesa di esecuzione?" In questo caso, il gestore del clic del mouse e il timer sono in uno stato in sospeso. Il browser ne seleziona uno (gestore di clic) e lo esegue. Il timer attenderà il successivo periodo di tempo disponibile nella coda di esecuzione.

Si noti che durante l'esecuzione del gestore del clic del mouse, viene attivata la prima richiamata a intervallo. Proprio come la richiamata con timer, verrà accodato. Si noti, tuttavia, che quando l'intervallo si attiva di nuovo (mentre il timer-callback è in esecuzione) verrà rimosso dalla coda. Se tutti i callback a intervallo "sono stati messi in coda durante l'esecuzione di una grossa porzione di codice, si tradurrebbe in un mucchio di funzioni in attesa di essere chiamate senza ritardi tra il loro completamento. Invece, i browser tendono ad aspettare fino a quando non rimangono più funzioni. coda prima di aggiungerne un altro alla coda.

Possiamo quindi osservare il caso in cui la terza attivazione dell'intervallo-callback coincide con il momento in cui è già in esecuzione. Questo illustra un punto importante: gli intervalli non si preoccupano di ciò che è attualmente in esecuzione, verranno aggiunti alla coda senza considerare il periodo di ritardo tra le esecuzioni.

Infine, dopo il completamento del secondo intervallo di callback, vediamo che non è rimasto nulla da eseguire per il motore JavaScript. Ciò significa che il browser è di nuovo in attesa di nuovi eventi asincroni. Ciò accadrà al contrassegno di 50 ms, dove la richiamata a intervallo si attiverà di nuovo. A questo punto, non ci sarà nulla a bloccarlo, quindi funzionerà immediatamente.

Diamo un'occhiata a un esempio che illustra bene la differenza tra setTimeout e setInterval.
setTimeout (function() (/ * Qualche lungo blocco di codice ... * / setTimeout (arguments.callee, 10);), 10); setInterval (funzione () (/ * Alcuni lunghi blocchi di codice ... * /), 10);
Queste due opzioni sono equivalenti a prima vista, ma in realtà non lo sono. Il codice che utilizza setTimeout avrà sempre un ritardo di almeno 10 ms dopo la chiamata precedente (può essere maggiore, ma non può mai essere inferiore), mentre il codice che utilizza setInterval tenderà a essere chiamato ogni 10 ms indipendentemente da quando è stata eseguita la chiamata precedente.

Ricapitoliamo quanto sopra:
- I motori JavaScript utilizzano un ambiente a thread singolo, trasformando gli eventi asincroni in una coda in attesa di esecuzione,
- Le funzioni setTimeout e setInterval vengono eseguite in modi fondamentalmente diversi in codice asincrono,
- Se il timer non può essere eseguito al momento, verrà ritardato fino al punto di esecuzione successivo (che sarà più lungo del ritardo desiderato),
- Gli intervalli (setInterval) possono essere eseguiti uno dopo l'altro senza ritardi se la loro esecuzione richiede più tempo del ritardo specificato.

Tutto questo è un'informazione estremamente importante per lo sviluppo. Sapere come funziona un motore JavaScript, specialmente con molti eventi asincroni (cosa che accade spesso), pone un'ottima base per la creazione di applicazioni avanzate.

  • A partire dal:
  • Registrato: 2014.07.08
  • Messaggi: 3,896
  • Piace: 497

Argomento: SetTimeOut e SetInterval, quale è meglio usare in JavaScript?

Per eseguire il codice più volte a intervalli regolari, usa la funzione setInterval... Tuttavia, presenta una serie di svantaggi, principalmente un comportamento diverso nei diversi browser.

La prima differenza è la differenza quando il timer è impostato per l'avvio successivo. Creiamo un piccolo test: misureremo il tempo trascorso dall'inizio della corsa precedente e dalla sua fine.

var d1 = nuova data (), d2 = nuova data (); setInterval (function () (var d = new Date (); document.body.innerHTML + = (d - d1) + "" + (d - d2) + "
"; // Metti un'etichetta all'inizio della funzione d1 = new Date (); while (new Date () - d1< 200); // ничего не делаем 200 миллисекунд // И в конце функции d2 = new Date(); }, 1000);

L'output sarà informativo a partire dalla seconda riga.

In Firefox, Opera, Safari e Chrome la situazione sarà simile: il primo numero sarà approssimativamente uguale a 1000, il secondo - 200 in meno. La differenza sarà solo nell'intervallo di valori. La più piccola variazione in Chrome e Opera.

2 Rispondi per PunBB (a cura di PunBB 2017.06.08 16:45)

  • A partire dal: Mosca, Sovchoznay 3, app. 98
  • Registrato: 2014.07.08
  • Messaggi: 3,896
  • Piace: 497

Un'altra differenza meno evidente e più difficile da riprodurre, ma che a volte può causare molti problemi, è la resistenza alle variazioni dell'ora del sistema. Se esegui il prossimo test

setInterval (function () (document.body.innerHTML = Math.random ();), 500);

E dopo l'avvio, reimposta l'ora del sistema di un minuto, quindi nei browser Firefox e Safari la modifica dei numeri si interromperà e dopo un minuto ricomincerà. Naturalmente, la traduzione manuale dell'ora di sistema è una situazione estremamente rara, ma molti sistemi sono configurati per sincronizzare automaticamente l'ora con i server su Internet, quindi in alcune situazioni questo fattore non può essere ignorato.

Un altro piccolo svantaggio della funzione setInterval è che per poter fermare la sua azione, devi ricordare il suo identificatore da qualche parte, il che non è sempre conveniente.

3 Rispondi per PunBB

  • A partire dal: Mosca, Sovchoznay 3, app. 98
  • Registrato: 2014.07.08
  • Messaggi: 3,896
  • Piace: 497

Ri: SetTimeOut e SetInterval, che è meglio usare in JavaScript?

Per eliminare gli svantaggi elencati di setInterval, puoi utilizzare più setTimeout.

Un'alternativa importante a setInterval è setTimeout ricorsivo:

/ ** invece di: var timerId = setInterval (function () (alert ("tick");), 2000); * / var timerId = setTimeout (funzione tick() (alert ("tick"); timerId = setTimeout (tick, 2000);), 2000);

Nel codice sopra, l'esecuzione successiva è pianificata immediatamente dopo quella precedente.

setTimeout ricorsivo è un metodo di temporizzazione più flessibile rispetto a setInterval, poiché il tempo fino all'esecuzione successiva può essere pianificato in modo diverso, a seconda dei risultati di quello corrente.

Ad esempio, abbiamo un servizio che interroga il server per nuovi dati ogni 5 secondi. Se il server è sovraccarico, puoi aumentare l'intervallo di polling a 10, 20, 60 secondi ... E poi ripristinarlo quando tutto è normalizzato.

Se abbiamo regolarmente attività che caricano il processore, possiamo stimare il tempo impiegato per la loro esecuzione e pianificare il prossimo avvio prima o poi.

4 Rispondi per PunBB

  • A partire dal: Mosca, Sovchoznay 3, app. 98
  • Registrato: 2014.07.08
  • Messaggi: 3,896
  • Piace: 497

Ri: SetTimeOut e SetInterval, che è meglio usare in JavaScript?

Il ricorsivo setTimeout garantisce una pausa tra le chiamate, setInterval no.

Confrontiamo i due codici. Il primo usa setInterval:

variabile i = 1; setInterval (funzione () (funzione (i);), 100);

Il secondo utilizza un setTimeout ricorsivo:

variabile i = 1; setTimeout (funzione run() (func (i); setTimeout (run, 100);), 100);

Con setInterval, il timer interno scatterà esattamente ogni 100 ms e chiamerà func (i):

La vera pausa tra le chiamate func con setInterval è inferiore a quella specificata nel codice!

Questo è naturale, perché il tempo di funzionamento della funzione non viene preso in considerazione in alcun modo, si "mangia" parte dell'intervallo.

È anche possibile che func si sia rivelato più complicato di quanto ci aspettassimo e abbia impiegato più di 100 ms per l'esecuzione.

In questo caso, l'interprete attenderà il completamento della funzione, quindi controllerà il timer e, se l'ora per chiamare setInterval è già arrivata (o è passata), la chiamata successiva avverrà immediatamente.

Se la funzione impiega più tempo della pausa setInterval, le chiamate verranno eseguite senza interruzioni.

5 Rispondi per senpai

  • A partire dal: Gerusalemme
  • Registrato: 2015.06.02
  • Messaggi: 958
  • Piace: 274

Ri: SetTimeOut e SetInterval, che è meglio usare in JavaScript?

Tutto dipende dal compito da svolgere. Inizialmente, SetTimeOut viene utilizzato per avviare il timer una volta e SetInterval per avviare il ciclo. Ma entrambe le funzioni possono essere utilizzate per scorrere gli script, se, ad esempio, vengono eseguite in modo ricorsivo nella funzione SetTimeOut, agirà in modo pratico simile a SetInterval.

Lo svantaggio di SetInterval al momento è che non tiene conto del tempo di esecuzione dello script (funzione) stesso e se, ad esempio, lo si utilizza per richieste pesanti, l'intervallo di tempo sarà notevolmente ridotto e possono differire nei diversi browser.

Ma ancora una volta, ripeto, se la funzione o la richiesta viene ridotta al minimo, è improbabile che l'utente finale senta la differenza.
Pertanto, cosa usare, ognuno decide per se stesso.

Fonte: http://learn.javascript.ru/settimeout-setinterval

Quasi tutte le implementazioni JavaScript hanno un timer di pianificazione interno che consente di pianificare una chiamata di funzione dopo un periodo di tempo specificato.

In particolare, questa funzionalità è supportata nei browser e nel server Node.JS.

impostaTimeout

Sintassi:

var timerId = setTimeout (func / code, delay [, arg1, arg2 ...])

Opzioni:

  • funzione / codice
    • Una funzione o una riga di codice da eseguire.
    • La stringa è supportata per compatibilità e non è consigliata.
  • ritardo
    • Ritardo in millisecondi, 1000 millisecondi equivalgono a 1 secondo.
  • arg1, arg2...
    • Argomenti da passare alla funzione. Non supportato in IE9-.
    • La funzione verrà eseguita dopo il tempo specificato nel parametro delay.

Ad esempio, il codice seguente chiamerà alert ("Hello") dopo un secondo:

funzione funzione()(avviso ("Ciao");) setTimeout (func, 1000);

Se il primo argomento è una stringa, l'interprete crea una funzione anonima da quella stringa.

Cioè, un tale record funziona esattamente allo stesso modo:

SetTimeout ("avviso (" Ciao ")", 1000);

Usa invece le funzioni anonime:

ImpostaTimeout ( funzione ()(avviso ("Ciao")), 1000);

Parametri e contesto della funzione

In tutti i browser moderni, pensando a IE10, setTimeout consente di specificare i parametri delle funzioni.

L'esempio seguente mostrerà "Ciao, sono Vasya" ovunque tranne IE9-:

funzione sayHi (chi)(avviso ("Ciao, sono" + chi);) setTimeout (sayHi, 1000, "Vasya");

... Tuttavia, nella maggior parte dei casi è necessario il supporto per il vecchio IE e non consente di specificare argomenti. Pertanto, per passarli, la chiamata è racchiusa in una funzione anonima:

funzione sayHi (chi)(avviso ("Ciao, io" + chi);) setTimeout ( funzione ()(direCiao ("Vasya")), 1000);

La chiamata tramite setTimeout non passa questo contesto.

In particolare, la chiamata al metodo di un oggetto tramite setTimeout funzionerà nel contesto globale. Questo può portare a risultati errati.

Ad esempio, chiamiamo user.sayHi() dopo un secondo:

funzione Utente (id) funzione ()(avviso (questo .id);); ) var utente = nuovo Utente (12345); setTimeout (user.sayHi, 1000); // previsto 12345, ma stamperà "non definito"

Poiché setTimeout eseguirà la funzione user.sayHi nel contesto globale, non sarà in grado di accedere all'oggetto tramite questo.

In altre parole, queste due chiamate a setTimeout fanno la stessa cosa:

// (1) una riga setTimeout (user.sayHi, 1000); // (2) stessa cosa su due righe var func = utente.sayHi; setTimeout (funzione, 1000);

Fortunatamente anche questo problema si risolve facilmente creando una funzione intermedia:

funzione Utente (id)(questo .id = id; questo .sayHi = funzione ()(avviso (questo .id);); ) var utente = nuovo Utente (12345); setTimeout ( funzione ()(utente.sayHi ();), 1000);

La funzione wrapper viene utilizzata per passare argomenti tra browser e memorizzare il contesto di esecuzione.

Annulla l'esecuzione

La funzione setTimeout restituisce un timerId che può essere utilizzato per annullare un'azione.

Sintassi:

ClearTimeout (ID timer)

Nell'esempio seguente, impostiamo un timeout e quindi cancelliamo (cambiamo idea). Di conseguenza, non succede nulla.

var timerId = setTimeout ( funzione ()(avviso (1)), 1000); clearTimeout (timerId);

setInterval

Il metodo setInterval ha una sintassi simile a setTimeout.

var timerId = setInterval (func / code, delay [, arg1, arg2 ...])

Il significato degli argomenti è lo stesso. Ma, a differenza di setTimeout, avvia l'esecuzione di una funzione non una volta, ma la ripete regolarmente a un intervallo di tempo specificato. Puoi interrompere l'esecuzione chiamando:

ClearInterval (ID timer)

Il seguente esempio, all'avvio, visualizzerà un messaggio ogni due secondi finché non si fa clic sul pulsante Stop:

<input type = "pulsante" onclick = "clearInterval (timer)" value = "(! LANG: Stop" > !} <sceneggiatura> variabile i = 1; var timer = setInterval ( funzione ()(allerta (i++)), 2000);sceneggiatura>

Accodamento e sovrapposizione di chiamate in setInterval

La chiamata a setInterval (funzione, ritardo) inserisce la funzione da eseguire dopo l'intervallo di tempo specificato. Ma qui c'è una sottigliezza.

In effetti, la pausa tra le chiamate è inferiore all'intervallo specificato.

Ad esempio, prendi setInterval (function () (func (i ++)), 100). Esegue la funzione ogni 100ms, incrementando ogni volta il contatore.

Nell'immagine sottostante, il blocco rosso è il tempo di esecuzione della funzione. Il tempo tra il blocco è il tempo tra gli inizi della funzione ed è inferiore al ritardo impostato!

Cioè, il browser avvia l'avvio della funzione ordinatamente ogni 100 ms, senza tenere conto del tempo di esecuzione della funzione stessa.

Succede che l'esecuzione di una funzione richieda più tempo del ritardo. Ad esempio, la funzione è complessa e la latenza è ridotta. Oppure la funzione contiene istruzioni alert/conferma/prompt che bloccano il thread di esecuzione. In questo caso iniziano cose interessanti.

Se la funzione non può essere avviata perché il browser è occupato, viene messa in coda ed eseguita non appena il browser è libero.

L'immagine seguente illustra cosa sta accadendo per una funzione che richiede molto tempo per l'esecuzione.

Una chiamata di funzione avviata da setInterval viene aggiunta alla coda e si verifica immediatamente quando diventa possibile:

La seconda esecuzione della funzione avviene immediatamente dopo la fine della prima:

L'esecuzione non viene messa in coda più di una volta.

Se l'esecuzione di una funzione richiede più tempo di diverse esecuzioni pianificate, rimarrà comunque in coda una volta. Quindi non c'è "accumulo" di lanci.

Nell'immagine sottostante, setInterval tenta di eseguire la funzione in 200 ms e accoda la chiamata. A 300 ms e 400 ms, il timer si riattiva, ma non succede nulla.

La chiamata a setInterval (funzione, ritardo) non garantisce un reale ritardo tra le esecuzioni.

Ci sono momenti in cui il ritardo effettivo è maggiore o minore di quello specificato. In generale, non è un dato di fatto che ci sarà almeno un qualche tipo di ritardo.

Ripetizione di setTimeout annidato

Nei casi in cui non è necessaria solo la ripetizione regolare, ma è richiesto un ritardo tra gli avvii, setTimeout deve essere impostato nuovamente ogni volta che viene eseguita la funzione.

Di seguito è riportato un esempio che emette un avviso con intervalli di 2 secondi tra di loro.

<tipo di input = "pulsante" onclick = "clearTimeout (timer)" valore = "(! LANG: Stop" > !} <sceneggiatura> variabile i = 1; var timer = setTimeout ( funzione esegui ()(avviso (i ++); timer = setTimeout (run, 2000);), 2000);sceneggiatura>

Ci saranno ritardi fissi tra le esecuzioni sulla timeline di esecuzione. Illustrazione per un ritardo di 100 ms:

Ritardo minimo del timer

Il timer del browser ha la latenza più bassa possibile. Varia da circa zero a 4 ms nei browser moderni. In quelli più vecchi, può essere più alto e raggiungere i 15 ms.

Secondo lo standard, il ritardo minimo è di 4 ms. Quindi non c'è differenza tra setTimeout (.., 1) e setTimeout (.., 4).

I comportamenti setTimeout e setInterval a latenza zero sono specifici del browser.

  1. In Opera, setTimeout (.., 0) è uguale a setTimeout (.., 4). Viene eseguito meno frequentemente di setTimeout (.., 2). Questa è una caratteristica di questo browser.
  2. In Internet Explorer, un setInterval di ritardo zero (.., 0) avrà esito negativo. Questo vale in particolare per setInterval, ad es. setTimeout (.., 0) funziona bene.

Frequenza di risposta effettiva

Può essere attivato molto meno frequentemente.In alcuni casi, il ritardo potrebbe non essere 4ms, ma 30ms o addirittura 1000ms.

La maggior parte dei browser (desktop in primis) continua ad eseguire setTimeout / setInterval anche se la scheda è inattiva. Allo stesso tempo, alcuni di essi (Chrome, FF, IE10) riducono la frequenza minima del timer, fino a 1 volta al secondo. Si scopre che un timer funzionerà nella scheda "sfondo", ma raramente.

Quando si utilizza l'alimentazione a batteria, in un laptop, i browser possono anche abbassare la frequenza per eseguire il codice meno spesso e risparmiare la carica della batteria. IE è particolarmente famoso per questo. La riduzione può essere fino a più volte, a seconda delle impostazioni. Se il carico del processore è eccessivo, JavaScript potrebbe non essere in grado di elaborare i timer in tempo. Questo salterà alcune delle esecuzioni di setInterval.

Conclusione: dovresti essere guidato dalla frequenza di 4ms, ma non dovresti contare su di essa.

Emissione degli intervalli sulla console Il codice che conta gli intervalli tra le chiamate è simile al seguente:

var timeMark = nuova data; setTimeout ( funzione vai ()(var diff = new Date - timeMark; // stampa un altro ritardo sulla console invece che sulla pagina console .log (diff); // ricorda l'ora alla fine, // per misurare esattamente il ritardo tra le chiamate timeMark = nuova data; setTimeout (vai, 100); ), 100 );

Il trucco setTimeout (func, 0)

Questo trucco è degno di entrare negli annali degli hack JavaScript.

La funzione è racchiusa in setTimeout (func, 0) se si desidera eseguirla dopo la fine dello script corrente.

Il punto è che setTimeout non esegue mai una funzione subito. Pianifica solo la sua attuazione. Ma l'interprete JavaScript inizierà a eseguire le funzioni pianificate solo dopo l'esecuzione dello script corrente.

Di norma, setTimeout non può comunque eseguire una funzione con un ritardo pari a 0. Come detto in precedenza, solitamente il ritardo sarà di 4 ms. Ma la cosa principale qui è che l'esecuzione in ogni caso avverrà dopo l'esecuzione del codice corrente.

Per esempio:

risultato variabile; funzione mostraRisultato()(avviso (risultato);) setTimeout (showResult, 0); risultato = 2 * 2; // stamperà 4

Totale

I metodi setInterval (func, delay) e setTimeout (func, delay) consentono di eseguire func regolarmente / una volta dopo millisecondi di ritardo.

Entrambi i metodi restituiscono l'ID del timer. Viene utilizzato per interrompere l'esecuzione chiamando clearInterval / clearTimeout.

| | setInterval | setTimeout | || ----------- | ---------- | | Cronometraggio | C'è una chiamata rigorosamente sul timer. Se l'interprete è occupato, una chiamata entra in coda. Il tempo di esecuzione della funzione non viene preso in considerazione, quindi l'intervallo di tempo dalla fine di un'esecuzione all'inizio di un'altra può essere diverso. | Viene utilizzata una chiamata ricorsiva a setTimeout invece di setInterval dove è necessaria una pausa fissa tra le esecuzioni. | | Ritardo | Ritardo minimo: 4 ms. | Ritardo minimo: 4 ms. | | Funzioni del browser | Il ritardo 0 non funziona in IE | In Opera, la latenza zero è equivalente a 4 ms, gli altri ritardi vengono gestiti con precisione, inclusi 1 ms, 2 ms e 3 ms non standard. |

Nella programmazione in linguaggi di scripting, è periodicamente necessario creare una pausa, per sospendere l'esecuzione del programma per un po', quindi continuare a lavorare. Ad esempio, negli script VBS e PHP, sono possibili i seguenti metodi:

VBS: wscript.sleep 1500 (ferma per 1,5 secondi)

PHP: sonno (10); (fermati per 10 secondi)

Durante tali pause, il sistema runtime (PHP o VBS) facendo nulla... Uno sviluppatore che cerca di utilizzare intuitivamente qualcosa di simile in Javascript sarà spiacevolmente sorpreso. Un errore tipico quando si tenta di creare una pausa in Javascript è simile a questo:

Funzione badtest() (per (var i = 1; i< 10; i++) { window.setTimeout("document.getElementById("test1").value += " + i, 900) } }

Pensi che quando, passando per il ciclo, si tratta di disegnare la cifra successiva, il tuo? impostaTimeout interromperà onestamente il lavoro di Javascript, attenderà 0,9 secondi, aggiungerà il numero richiesto alla fine del campo di input e quindi continuerà a lavorare. Ma in realtà non lo è: setInterval e impostaTimeout in Javascript viene ritardata solo l'azione (o funzione) indicata tra parentesi. Nel nostro esempio, accadrà quanto segue:

  1. io = 1;
  2. posticipare l'aggiunta del numero "1" al campo di input di 0,9 secondi;
  3. subito dopo aver impostato questo problema, il ciclo prosegue: i = 2;
  4. posticipare l'aggiunta del numero "2" al campo di input di 0,9 secondi;

Subito significa, ad esempio, 1 ms (cioè incommensurabilmente piccolo, rispetto a 900 ms): il ciclo svolgerà il suo lavoro quasi istantaneamente, creando più task in sospeso dallo stesso momento. Ciò significa che tutte le attività di "disegno" in sospeso verranno completate quasi contemporaneamente, senza pause tra l'aggiunta di nuovi numeri. Il ciclo si avvia; tutto si blocca per 0,9 s; e shirrr - tutti i numeri vengono sparati in fila uno dopo l'altro.

E come, in tal caso, è corretto applicare impostaTimeout? È complicato. Devo chiamare la funzione ricorsivamente(dall'interno della funzione, la stessa funzione), e affinché questo processo non sia infinito, impostare la condizione di arresto (ad esempio, il valore del numero stampato):

Funzione welltest() (if (i< 9) { document.getElementById("test2").value += ++i window.setTimeout("welltest()", 400) } }

E un'altra variabile io dovrà essere inizializzato al di fuori della funzione, ad esempio in questo modo:

Ora tutto funziona come dovrebbe (abbiamo ridotto il tempo di ritardo da 0,9 sa 0,4 s). Ma per tali compiti è più logico usare not impostaTimeout un setInterval(anche se ciò richiederebbe due funzioni):

Funzione besttest() (window.i = 0 window.timer1 = window.setInterval ("draw ()", 400)) function draw() (document.getElementById ("test3"). Valore + = ++ i if (i > = 9) clearInterval (window.timer1))

Caratteristica del metodo Javascirpt setInterval il fatto che non passi "da solo", deve essere fermato con un metodo speciale clearInterval... E per chiarire cosa interrompere, all'attività di azione differita viene assegnato un identificatore speciale: un timer: window.timer1 = window.setInterval (...).

Gli identificatori possono anche essere assegnati alle attività create dal metodo impostaTimeout... Tutti gli ID timer devono essere diversi l'uno dall'altro (univoci all'interno della finestra del browser corrente). Quindi puoi creare diverse attività nella finestra che utilizzano azioni differite e queste attività verranno eseguite in parallelo (un po' come contemporaneamente, se il computer ha risorse sufficienti), il che è praticamente impossibile in PHP o VBS.

Ecco un esempio di una pagina con più timer Javascript in esecuzione contemporaneamente: setinterval.htm (funzioni JavaScript nel file setinterval.js). Il funzionamento di tutti i timer di pagina (ad eccezione del menu) può essere interrotto premendo il tasto Esc. Tutti i timer di esempio si basano su "naturale" (non astratto io ++) conto alla rovescia - tempo o distanza. Tutti gli "orologi" sono appositamente desincronizzati (per chiarezza). I timer basati sulla distanza vengono utilizzati nel menu "indicatore" e nel menu a discesa (a discesa).

Menu a discesa

Il nostro menu estraibile è in realtà estraibile (da sotto l'"intestazione"): ci sono degli spazi tra gli elementi per vedere come si estrae. Inaspettatamente, si è scoperto che non possiamo fare un'uscita altrettanto fluida per elenchi di lunghezze diverse, probabilmente a causa delle basse prestazioni del computer (AMD Athlon 999 MHz).

È abbastanza ovvio che per la bellezza e l'armonia è necessario che appaiano contemporaneamente elenchi di diverse voci di menu. Cioè, gli elenchi più lunghi dovrebbero scomparire a un ritmo più veloce, quelli più brevi - a un ritmo inferiore. Sembrerebbe che possa essere implementato in questo modo:

  1. Impostiamo il tempo totale di "partenza", ad esempio, in 200 ms.
  2. Se l'elenco a discesa ha un'altezza di 20 px, è ovvio che possiamo spostarlo in basso di un pixel alla volta di 10 ms - e quindi in 200 ms l'intero elenco verrà visualizzato.
  3. Se il menu a discesa è alto 40 px, per adattarsi allo stesso tempo, dobbiamo spostarlo in basso di un pixel alla volta in 5 ms.

Secondo questa logica, se l'elenco a discesa è alto 200 px, dobbiamo spostarlo in basso di un pixel alla volta in 1 ms. Ma questa velocità non funziona sul nostro computer: il browser semplicemente non ha il tempo di disegnare la nuova posizione dell'elenco in un millisecondo. Sì. Javascript ha il tempo di contare (cosa c'è da contare?), Ma il browser (Firefox) non ha il tempo di visualizzare. Una situazione tipica per il web.

Pertanto, è possibile equalizzare più o meno il tempo di uscita dal menu solo con l'aiuto delle stampelle e non è ancora chiaro come funzionerà su un computer più veloce. Ma dobbiamo contare sul più lento, giusto? L'algoritmo (senza tener conto della velocità del computer) risulta essere qualcosa del genere:

  1. Impostiamo il tempo totale di checkout della lista: time = 224 (ms).
  2. Impostiamo il tempo minimo per un intervallo in un ciclo: ritardo = 3 (ms).
  3. Imposta il passo minimo per spostare l'elenco: offset = 1 (px).
  4. Modifichiamo tutto questo a seconda dell'altezza della lista: 1) aumentiamo il tempo di ritardo (intervallo) in modo inversamente proporzionale all'altezza e direttamente proporzionale al tempo totale (a quota 224, il coefficiente è 1); 2) se l'altezza è superiore a 40 px, aumentare il passo minimo proporzionalmente all'altezza. La costante "40" è ottenuta empiricamente per il computer più lento. I test su un computer Pentium 4 CPU 2,53GHz hanno rivelato esattamente lo stesso numero - 40. Altrimenti, i timer si scatenano, le liste non tengono il passo.

Ora le liste si stanno più o meno diffondendo. Per un tempo più o meno simile. Nella pagina setinterval.htm.

Ed ecco Bru-baffi:

Funzione slide_do (obj, maxtop, offset) (if (getTopLeft (obj) .top< maxtop) { obj.style.top = getTopLeft(obj).top + offset } else { if (obj && obj.timer1) { clearInterval(obj.timer1) obj.timer1 = null } } }

La funzione stessa, che porta fuori dal menu gli elenchi annidati, è, come puoi vedere, molto semplice. Resta solo da eseguirlo con qualcosa del genere:

Ts.timer1 = setInterval (function () (slide_do (ts, maxtop, offset)), delay)

Bene, prima di iniziare, calcola tutti questi maxtop e offset e metti anche l'elenco nella posizione mintop. A cosa serve la funzione "preliminare" diapositiva () 40 linee di dimensione. E tutti insieme - nel file setinterval.js. Sì, e questa merda non funzionerà senza un foglio di stile incluso.