2011-02-06 16 views
8

Tengo un bucle for que itera más de 10.000 veces en un código de JavaScript. El bucle for crea y agrega < div etiquetas en un cuadro en la página actual DOM.Javascript: ¿Cómo poner un simple retraso entre la ejecución del código javascript?

for(i = 0; i < data.length; i++) 
{ 
    tmpContainer += '<div> '+data[i]+' </div>'; 
    if(i % 50 == 0) { /* some delay function */ } 
} 
containerObj.innerHTML = tmpContainer; 

Quiero poner un retraso cada 50 < div> etiquetas por lo que será el código en el lugar de

/* some delay function */ 

porque su tomar demasiado tiempo para cargar todos los 10.000 < div> etiquetas. Quiero actualizar el cuadro en trozos de 50 < div> etiquetas.

gracias de antemano.

Respuesta

15

Hay un truco útil en estas situaciones: use un setTimeout con 0 milisegundos. Esto hará que su JavaScript para rendir al navegador (para que pueda realizar su prestación, responder a la entrada del usuario y así sucesivamente), pero sin forzarlo que esperar una cierta cantidad de tiempo:

for (i=0;i<data.length;i++) { 
    tmpContainer += '<div> '+data[i]+' </div>'; 
    if (i % 50 == 0 || i == data.length - 1) { 
     (function (html) { // Create closure to preserve value of tmpContainer 
      setTimeout(function() { 
       // Add to document using html, rather than tmpContainer 

      }, 0); // 0 milliseconds 
     })(tmpContainer); 

     tmpContainer = ""; // "flush" the buffer 
    } 
} 

Nota: TJ Crowder menciona correctamente a continuación que el código anterior creará funciones innecesarias en cada iteración del ciclo (una para configurar el cierre y otra como argumento para setTimeout). Es poco probable que sea un problema, pero si lo desea, puede consultar his alternative que solo crea la función de cierre una vez.

Una palabra de advertencia: a pesar de que el código anterior proporcionará una experiencia de representación más placentera, no es aconsejable tener 10000 etiquetas en una página. Cualquier otra manipulación de DOM será más lenta después de esto porque hay muchos más elementos para atravesar, y un cálculo de reflujo mucho más costoso para cualquier cambio en el diseño.

+1

Eso funcionará, pero dos comentarios: 1. Crea innecesariamente una ** nueva ** función cada vez que llegue a 50 divs. Eso es 199 funciones innecesarias. Probablemente está bien, pero aún así, evitable. 2. Es más eficiente compilar HTML en una matriz de cadenas, y luego usar 'a.join (" ")' para crear una cadena grande cuando hayas terminado, que usar concatenación de cadenas para construir el HTML. –

+0

@ T.J. tiene razón sobre ambos puntos, pero no me molesté por simplicidad: 1. La creación de funciones rara vez es un problema de rendimiento, especialmente cuando su cuello de botella es el DOM, 2. la concatenación de cadenas es solo un problema en IE, y a menudo más rápido en otros navegadores, pero incluso para IE, dado que estoy restableciendo 'tmpContainer' en una cadena vacía, las cadenas nunca se vuelven grandes;) –

+0

realmente buena solución. –

2

usted podría utilizar la función window.setTimeout para retrasar la ejecución de un código:

if(i % 50 == 0) { 
    window.setTimeout(function() { 
     // this will execute 1 second later 
    }, 1000); 
} 

Pero su javascript continuará ejecutando. No se detendrá.

1

me gustaría romper el código de la creación de los div s en una función, y luego programar la ejecución de esa función periódicamente a través de setTimeout, así:

function createThousands(data) { 
    var index; 

    index = 0; 
    doAChunk(); 

    function doAChunk() { 
     var counter; 

     for (counter = 50; counter > 0; --counter) { 
      // Are we done? 
      if (index >= data.length) { 
       // Yup 
       return; 
      } 

      // ...create a div... 

      // Move to the next 
      ++index; 
     } 

     // Schedule the next pass 
     setTimeout(doAChunk, 0); // 0 = defer to the browser but come back ASAP 
    } 
} 

Este utiliza un único cierre, para hacer el doAChunk trabajo. Ese cierre es elegible para la recolección de basura una vez que se termina su trabajo. (Más: Closures are not complicated)

Live example

+0

no resuelve su problema –

+0

@fehergeri: *¿Mi problema? ¿Huh? –

+0

@fehergeri: Oh, ya veo, querías decir * su * problema. Estaba lidiando con el problema de no hacer actualizaciones provisionales; Reflow es algo completamente diferente. –

1

se tarda mucho tiempo porque los reflujos. deberías crear un fragmento de documento y luego agregar los puntos.

When does reflow happen in a DOM environment?

Javascript Performance - Dom Reflow - Google Article

dormir no va a resolver su problema

por el contrario, que la creación de una cadena que contiene el innerHTML y el complemento a InnerHtml.el material de cadena realmente no necesita un gran rendimiento, pero cuando ejecuta el comando .innerhtml, inicia un proceso, que analiza su cadena y crea elementos y los agrega. no puedes interrumpir o agregar un retraso.

el proceso innerhtml no se puede dormir o interrumpir.

necesita generar los elementos uno por uno, y después de agregar 50 elementos, cree una demora settimeout.

var frag = document.createDocumentFragment(); 

function addelements() { 

    var e; 
    for(i=0;i<50;++i) { 
     e = document.createElement('div'); 
     frag.appendChild(e); 
    } 
    dest.appendChild(frag); 
    window.setTimeout(addelements,1000); 

} 
-1

Aquí está el verdadero truco para poner un retraso en javascript sin tener que colgar el navegador. ¡Necesita usar una función ajax con un método sincrónico que llamará a una página php y en esa página php puede usar la función php sleep()! http://www.hklabs.org/articles/put-delay-in-javascript

+2

Tenga en cuenta que [las respuestas solo de enlace] (http://meta.stackoverflow.com/tags/link-only-answers/info) no se recomiendan, por lo que las respuestas deberían ser el punto final de una búsqueda de una solución (vs. otra escala más de referencias, que tienden a quedar obsoletas en el tiempo). Considere agregar una sinopsis independiente aquí, manteniendo el enlace como referencia. – kleopatra

Cuestiones relacionadas