2010-06-08 14 views
12

Ho alcune funzioni javascript che richiedono circa 1 o 3 secondi. (alcuni loop o codice di template mooML.)Mostra avanzamento di esecuzione javascript

Durante questo periodo, il browser è appena congelato. Ho provato a mostrare un'animazione di "caricamento" (immagine gif) prima di iniziare l'operazione e nasconderla dopo. ma semplicemente non funziona. Il browser si blocca prima di poter eseguire il rendering dell'immagine e lo nasconde immediatamente al termine della funzione.

C'è qualcosa che posso fare per dire al browser di aggiornare lo schermo prima di andare in esecuzione javascript., Qualcosa come Application.DoEvents o thread di background worker.

Quindi qualsiasi commento/suggerimento su come mostrare l'avanzamento dell'esecuzione di javascript. Il mio browser di destinazione principale è IE6, ma dovrebbe funzionare anche su tutti i browser più recenti

+0

Hai provato a inserire il javascript nell'evento window.onload? – NibblyPig

+0

@ SLC non ci appartiene – Midhat

risposta

19

Ciò è dovuto a tutto in IE6 in esecuzione nello stesso thread - anche l'animazione del GIF.

L'unico modo per assicurarsi che la gif venga visualizzata prima dell'avvio è staccando l'esecuzione.

function longRunningProcess(){ 
    .... 

    hideGif(); 
} 

displayGif(); 
window.setTimeout(longRunningProcess, 0); 

Ma questo sarà ancora rendere il browser congelato mentre longRunningProcess esegue.
Al fine di consentire l'interazione si dovrà rompere il codice a frammenti più piccoli, forse come questo

var process = { 
    steps: [ 
     function(){ 
      // step 1 
      // display gif 
     }, 
     function(){ 
      // step 2 
     }, 
     function(){ 
      // step 3 
     }, 
     function(){ 
      // step 4 
      // hide gif 
     } 
    ], 
    index: 0, 
    nextStep: function(){ 
     this.steps[this.index++](); 
     if (this.index != this.steps.length) { 
      var me = this; 
      window.setTimeout(function(){ 
       me.nextStep(); 
      }, 0); 
     } 
    } 
}; 

process.nextStep(); 
+0

impressionante ... bella soluzione. Grazie – Novice

1

Forse è possibile inserire un ritardo tra la visualizzazione della gif animata e l'esecuzione del codice pesante.

Mostra gif, e chiamata:

window.setTimeout(myFunction, 100) 

fare la roba pesante "myFunction".

0

Provare a impostare un cursore wait prima di eseguire la funzione e rimuoverla in seguito. In jQuery si può fare in questo modo:

var body = $('body'); 
body.css("cursor", "wait"); 
lengthyProcess(); 
body.css("cursor", ""); 
+2

E senza jQuery, è persino _shorter_! 'Document.body.style.cursor = "attendere"'. Magico! – Alsciende

+0

@Alsciende, in realtà, è più lungo. 'document.body.style.cursor =" wait "' contro '$ ('body'). css ('cursor', 'wait')', ma sono d'accordo che si dovrebbe sempre usare il metodo più semplice disponibile. –

+5

In realtà, la soluzione jQuery è più o meno 70K più lunga ... –

1

Devi usare un po 'di tecnica più sofisticata per mostrare lo stato di avanzamento della funzione di esecuzione lungo.

Diciamo che avere una funzione come questa che corre abbastanza a lungo:

function longLoop() { 
    for (var i = 0; i < 100; i++) { 
     // Here the actual "long" code 
    } 
} 

Per mantenere l'interfaccia reattivo e per mostrare i progressi (anche per evitare "lo script richiede troppo tempo ..." messaggi in alcuni browser) devi dividere l'esecuzione nelle varie parti.

function longLoop() { 
    // We get the loopStart variable from the _function_ instance. 
    // arguments.callee - a reference to function longLoop in this scope 
    var loopStart = arguments.callee.start || 0; 

    // Then we're not doing the whole loop, but only 10% of it 
    // note that we're not starting from 0, but from the point where we finished last 
    for (var i = loopStart; i < loopStart + 10; i++) { 
     // Here the actual "long" code 
    } 

    // Next time we'll start from the next index 
    var next = arguments.callee.start = loopStart + 10; 
    if (next < 100) { 

     updateProgress(next); // Draw progress bar, whatever. 
     setTimeout(arguments.callee, 10); 
    } 
} 

Non ho testato questo codice effettivo, ma ho già utilizzato questa tecnica prima.

+0

Mi piace questa soluzione, grazie! –

Problemi correlati