Evita javascript a lungo termine dal blocco del browser

Ho JavaScript che esegue un sacco di calcoli e valori di lettura / scrittura da / verso il DOM. La pagina è enorme quindi spesso questo blocca il browser fino a un minuto (a volte più lungo con IE) con il 100% di utilizzo della CPU.

Ci sono risorse sull’ottimizzazione di JavaScript per evitare che ciò accada (tutto quello che posso trovare è come distriggersre l’avviso di script a lungo termine di Firefox)?

se è ansible trasformare l’algoritmo di calcolo in qualcosa che può essere chiamato in modo iterativo, è ansible rilasciare il controllo del browser a intervalli frequenti utilizzando setTimeout con un valore di timeout breve.

Ad esempio, qualcosa come questo …

function doCalculation() { //do your thing for a short time //figure out how complete you are var percent_complete=.... return percent_complete; } function pump() { var percent_complete=doCalculation(); //maybe update a progress meter here! //carry on pumping? if (percent_complete<100) { setTimeout(pump, 50); } } //start the calculation pump(); 

Usa i timeout.

Inserendo il contenuto del tuo loop in funzioni separate e chiamandoli da setTimeout () con un timeout di 50 o giù di lì, il javascript produrrà il controllo del thread e tornerà un po ‘di tempo dopo, consentendo all’interfaccia utente di ottenere un guarda dentro.

C’è un buon lavoro qui .

Qualche tempo fa avevo bloggato sulle prestazioni del browser , ma vorrei riassumere quelle relative al DOM per te qui.

  • Aggiorna il DOM il meno frequentemente ansible. Apporta le tue modifiche agli oggetti DOM in memoria e aggiungili solo una volta al DOM.
  • Usa innerHTML. È più veloce dei metodi DOM nella maggior parte dei browser.
  • Utilizzare la delega dell’evento anziché la normale gestione degli eventi.
  • Scopri quali chiamate sono costose ed evitali. Ad esempio, in jQuery, $ (“div.className”) sarà più costoso di $ (“# someId”).

Poi ci sono alcuni relativi a JavaScript stesso:

  • Loop il meno ansible. Se si dispone di una funzione che raccoglie i nodes DOM e un’altra che li elabora, si esegue il ciclo due volte. Invece, passa una funzione anonima alla funzione che raccoglie i nodes ed elabora i nodes mentre li stai raccogliendo.
  • Utilizza le funzionalità native quando ansible. Ad esempio, per Ogni iteratore.
  • Usa setTimeout per far respirare il browser una volta ogni tanto.
  • Per le funzioni costose dotate di output idempotenti, memorizzare i risultati in cache in modo da non doverli ricalcolare.

Ce ne sono altri sul mio blog (link sopra).

Questo è ancora un po ‘sanguinante, ma Firefox 3.5 ha queste cose chiamate Web Workers, ma non sono sicuro del loro supporto in altri browser.

Il signor Resig ha un articolo su di loro qui: http://ejohn.org/blog/web-workers/

E il Simulated Annealing è probabilmente l’esempio più semplice di esso, se noterai che il logo spinning di Firefox non si blocca, quando i thread worker stanno facendo le loro richieste (quindi non congelando il browser).

Puoi provare a eseguire calcoli a lunga esecuzione in thread (vedi JavaScript e Thread ), sebbene non siano molto portabili.

Puoi anche provare a utilizzare qualche profiler Javascript per trovare i colli di bottiglia delle prestazioni. Firebug supporta la creazione di profili di javascript.

La mia esperienza è che la manipolazione DOM, specialmente in IE, è molto più un problema per le prestazioni rispetto al “core” JavaScript (looping, ecc.).

Se stai costruendo i nodes, in IE è molto più veloce farlo costruendo una stringa HTML e quindi impostando innerHTML su un contenitore che usando metodi DOM come createElement / appendChild.

Potresti provare ad abbreviare il codice

  $(xmlDoc).find("Object").each(function(arg1) { (function(arg1_received) { setTimeout(function(arg1_received_reached) { //your stuff with the arg1_received_reached goes here }(arg1_received), 0) })(arg1) }(this)); 

o per provare i loop “for”

 for (var i = 0 ; i < 10000 ; i = i + 1) { (function(arg1_received) { setTimeout(function(arg1_received_reached) { //your stuff with the arg1_received_reached goes here }(arg1_received), 0) })(arg1_to_send) } 

Ho avuto lo stesso problema e i miei clienti lo hanno segnalato come errore "Kill page". Ma ora ho una soluzione migliore per questo. 🙂