Molto spesso vedere in codice JavaScript librerie in questo modo:chiamata setTimeout senza indugio
setTimeout(function() {
...
}, 0);
Vorrei sapere perché utilizzare tale codice wrapper.
Molto spesso vedere in codice JavaScript librerie in questo modo:chiamata setTimeout senza indugio
setTimeout(function() {
...
}, 0);
Vorrei sapere perché utilizzare tale codice wrapper.
molto semplificato:
browser sono singolo thread e questo singolo filo (thread UI) è condivisa tra il motore di rendering e il motore js.
Se la cosa che si vuole fare richiede molto tempo (stiamo parlando dei cicli qui ma ancora) potrebbe arrestare (paus) il rendering (flusso e vernice).
Nei browser esiste anche "Il secchio" in cui tutti gli eventi vengono prima messi in attesa che il thread dell'interfaccia utente venga eseguito con qualsiasi cosa stia facendo. Non appena il thread è terminato, viene visualizzato nel bucket e preleva l'attività prima in linea.
Utilizzando setTimeout
si crea una nuova attività nel bucket dopo il ritardo e si lascia che il thread lo gestisca non appena è disponibile per ulteriori operazioni.
Una storia:
dopo 0 ms ritardo creare una nuova attività della funzione e metterlo nel secchio. In quel momento esatto il thread dell'interfaccia utente è occupato da mentre fa qualcos'altro, e ci sono già altre attività nel bucket . Dopo 6ms il thread è disponibile e ottiene l'attività in del tuo, bene, sei il prossimo. Ma cosa? Questa è stata una cosa enorme! Ha stato come foreeeeeever (30ms) !!
Finalmente, ora il thread è terminato e arriva e ottiene l'attività .
La maggior parte dei browser ha un ritardo minimo superiore a 0, quindi mettere 0 come ritardo significa: Mettere questa attività nel carrello AL PIÙ PRESTO. Ma dire alla UA di metterlo nel secchio ASAP non è garanzia che verrà eseguito in quel momento. Il secchio è come l'ufficio postale, potrebbe essere che ci sia una lunga coda di altri compiti. Gli uffici postali sono anche single threaded con una sola persona che aiuta tutto il compito ...scusate i clienti con i loro compiti. Il tuo compito deve essere in linea come tutti gli altri.
Se il browser non implementa il proprio ticker, utilizza i cicli di tick del sistema operativo. I browser meno recenti avevano ritardi minimi compresi tra 10 e 15 ms. HTML5 specifies che se il ritardo è inferiore a 4 ms, UA lo aumenterà a 4 ms. Si dice che sia consistent across browsers released in 2010 and onward.
Vedere How JavaScript Timers Work di John Resig per ulteriori dettagli.
Edit: vedere anche What the heck is the event loop anyway? da Philip Roberts da JSConf UE 2014. Questa è la visione obbligatoria per tutte le persone che toccano codice di front-end.
Per consentire l'esecuzione di qualsiasi timeout impostato in precedenza.
ci sono un paio di motivi per cui si dovrebbe fare questo
setTimeout
o setInterval
di eseguireQuando si desidera eseguire resto del codice senza aspettare quello precedente per finire è necessario aggiungere nel metodo anonimo passato a setTimeout funzione. In caso contrario, il codice attenderà precedente viene fatto
Esempio:
function callMe()
{
for(var i = 0; i < 100000; i++)
{
document.title = i;
}
}
var x = 10;
setTimeout(callMe, 0);
var el = document.getElementById('test-id');
el.innerHTML = 'Im done before callMe method';
Questo è il motivo che lo uso.
Oltre alle risposte precedenti vorrei aggiungere un altro scenario utile a cui riesco a pensare: "scappare" da un blocco try-catch. Un ritardo setTimeout all'interno di un blocco try-catch verrà eseguito all'esterno del blocco e qualsiasi eccezione si propagherà invece nello scope globale.
Forse lo scenario di esempio migliore: nel JavaScript di oggi, con l'uso più comune dei cosiddetti Deferred/Promises per i callback asincroni, si è (spesso) effettivamente in esecuzione all'interno di un try-catch. Deferred/Promises racchiudono il callback in un try-catch per essere in grado di rilevare e propagare un'eccezione come un errore nella catena asincrona. Questo va bene per le funzioni che devono essere presenti nella catena, ma prima o poi sarai "fatto" (cioè recuperato tutto il tuo ajax) e vuoi eseguire un semplice codice non asincrono dove non vuoi che siano le eccezioni " nascosto "più. Dojo AFAIK, Q di Kris Kowal, MochiKit e Google Closure lib utilizzano il wrapping try-catch (non jQuery però).
(In un paio di strane occasioni ho anche usato la tecnica per riavviare il codice in stile singleton senza causare la ricorsione. Sto facendo un teardown-restart nello stesso ciclo).
** SUGGERIMENTO PRO: ** Non è necessario il ', 0' alla fine. – vsync