2010-06-08 20 views
12

Tengo algunas funciones de javascript que tardan entre 1 y 3 segundos. (algunos bucles o código de plantillas mooML.)Mostrar el progreso de ejecución de javascript

Durante este tiempo, el navegador está congelado. Intenté mostrar una animación de "carga" (imagen gif) antes de comenzar la operación y ocultar las palabras posteriores. pero simplemente no funciona. El navegador se congela antes de que pueda procesar la imagen y la oculta inmediatamente cuando termina la función.

¿Hay algo que pueda hacer para decirle al navegador que actualice la pantalla antes de entrar en la ejecución de JavaScript?, Algo así como Application.DoEvents o hilos de trabajo en segundo plano.

Por lo tanto, cualquier comentario/sugerencia sobre cómo mostrar el progreso de ejecución de javascript. Mi navegador de destino principal es IE6, pero también debería funcionar en todos los navegadores más recientes

+0

¿Ha intentado poner el javascript en el evento window.onload? – NibblyPig

+0

@SLC no pertenece allí – Midhat

Respuesta

19

Esto se debe a que todo en IE6 ser ejecutado en el mismo hilo - incluso la animación del GIF.

La única manera de asegurarse de que se muestra el archivo .gif antes de comenzar es mediante la separación de la ejecución.

function longRunningProcess(){ 
    .... 

    hideGif(); 
} 

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

Pero esto hará que el navegador inactiva mientras se ejecuta longRunningProcess.
Con el fin de permitir la interacción que tendrá que romper su código en fragmentos más pequeños, tal vez como esta

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

increíble ... genial solución. Gracias – Novice

1

Quizás pueda poner un retraso entre mostrar el gif animado y ejecutar el código pesado.

Muestra el gif, y llamada:

window.setTimeout(myFunction, 100) 

hacer las cosas pesadas en "myFunction".

0

Intente configurar un cursor wait antes de ejecutar la función y luego eliminarla. En jQuery puede hacerlo de esta manera:

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

¡Y sin jQuery, es incluso _shorter_! 'document.body.style.cursor =" wait "'. ¡Mágico! – Alsciende

+0

@Alsciende, en realidad, es más largo. 'document.body.style.cursor =" wait "' contra '$ ('body'). css ('cursor', 'wait')', pero estoy de acuerdo en que siempre se debe usar el método más simple disponible. –

+5

En realidad, la solución jQuery es más o menos 70K más larga ... –

1

Usted tiene que usar un poco de técnica más sofisticada para mostrar el progreso de la función de larga ejecución.

Digamos que tiene una función como esta que corre el tiempo suficiente:

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

Para mantener la interfaz de respuesta y para mostrar el progreso (también para evitar "la escritura está tomando demasiado tiempo ..." mensajes en algunos navegadores) debe dividir la ejecución en varias partes.

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); 
    } 
} 

No he probado este código real, pero he utilizado esta técnica anteriormente.

+0

Me gusta esta solución, ¡gracias! –

Cuestiones relacionadas