2010-10-20 9 views
5

Recientemente comencé a trabajar con jQuery y hoy noté un problema extraño con la forma en que se comportaba para mí. Según tengo entendido, JavaScript tiene un solo hilo. Entonces todas sus operaciones deberían ejecutarse en una base FIFO. Sin embargo, este no parece ser el caso para mí. Por favor considere lo siguiente.jQuery no se ejecuta en el orden correcto?

CONFIGURACIÓN es el siguiente

HTML:

3 divs

  • div # 1 => contiene elementos de la cabecera, que se puede hacer clic para ejecutar la función de clasificación

  • div # 2 => contiene los datos que deben ordenarse

  • div # 3 => contiene un .gif básico que se utiliza para notificar al usuario de que alguna operación se está realizando

jQuery - contiene la función de clasificación que realiza la manipulación del DOM. Básicamente, lee datos de la página HTML, almacena en una matriz 2D y ordena la matriz. Luego borra div div 2 (data div) completamente y lo reconstruye, usando datos de la matriz ordenada. Se esperaba

EJECUCIÓN ser como sigue

  • usuario hace clic en uno de los encabezados para activar la función de clasificación
  • función de clasificación oculta div # 2 y muestra div # 3
  • función de clasificación es ejecutado
  • una vez que se completó la clasificación, div # 2 (div datos) se muestra y se div # 3 está oculta

Sin embargo, aquí es lo que parece ocurrir

  • usuario hace clic en los encabezados de

  • tipo se produce

  • ocultar y mostrar de divs ocurre en el último paso

Inicialmente, como no pude ver ningún divs que se muestra/oculta, asumí que estaba pasando demasiado rápido para que yo lo notara. Así que agregué un retraso a las funciones .show() y .hide() de jQuery. Una vez hecho esto, era bastante evidente que las acciones de mostrar y ocultar se estaban realizando al final.

* * SOLUCIÓN Después de mucho buscar, me las arreglé para conseguir este trabajo como esperaba utilizando jQuery .queue() y() .dequeue funciones. El talón de Aquiles aquí fue que tuve que insertar un retraso de 1 milisegundo entre cada operación. Entonces, y solo entonces, el navegador pudo ocultar/mostrar divs como yo quería.Por lo que las operaciones fue algo como esto:

var theQueue = $({}); // jQuery on an empty object 

theQueue.queue("testQueue", 
       function(next) { 
        $("#loadingIndicator").show(); 
        $("#cases").hide(); 
        next(); 
       } 
      ); 
theQueue.delay(1, "testQueue"); 

theQueue.queue("testQueue", 
       function(next) { 
        doSort(columnNumber); //SORT 
        next(); 
       } 
      ); 
theQueue.delay(1, "testQueue"); 

theQueue.queue("testQueue", 
       function(next) { 
        $("#loadingIndicator").hide(); 
        $("#cases").show(); 
        next(); 
       } 
      ); 

theQueue.dequeue("testQueue"); 

}

Desde luego, no soy un experto en la materia, pero yo creo que las operaciones deben estar ejecutando en el mismo orden como se les llama. ¿El navegador no está procesando en el orden correcto? ¿Cambia jQuery el orden de las operaciones para hacer las cosas más eficientes?

Si bien la "solución" hace el trabajo, no estoy convencido de que sea la mejor solución en este escenario. Hay alguna otra manera de hacer esto? Si es necesario, puedo proporcionar ejemplos de código de trabajo que demostrarán el problema. Gracias.

En una nota diferente, he notado con grandes conjuntos de datos, cuando el usuario hace clic en un elemento de encabezado para activar la ordenación, el navegador deja de responder. Me doy cuenta de que está ejecutando la función de ordenación, pero esperaba que hubiera una forma de evitar esto. ¿Alguna idea?

Respuesta

7

Las operaciones se están ejecutando en el mismo orden en que se llaman, pero el problema es que los elementos DOM y lo que se muestra en la pantalla son dos cosas separadas. El proceso que procesa los elementos en la pantalla se ejecuta en el mismo entorno de subproceso único que el código de JavaScript, por lo que no puede mostrar ningún cambio en el escenario hasta que finalice el guión.

Para que aparezcan los cambios, debe finalizar la secuencia de comandos y luego reanudarla una vez que el procesador haya tenido la oportunidad de mostrar los cambios.

Usted puede utilizar el método setTimeout para devolver el control al navegador, y obtener el resto del código para comenzar tan pronto como sea posible:

$("#loadingIndicator").show(); 
$("#cases").hide(); 

window.setTimeout(function(){ 

    doSort(columnNumber); //SORT 
    $("#loadingIndicator").hide(); 
    $("#cases").show(); 

}, 0); 
+0

Impresionante, gracias por la explicación fácil de seguir. Ahora estoy usando este método y debo decir que usa bastante menos código que el otro método de cola que estaba usando. Aclamaciones. – Harinder

1

.show() y .hide() son miembros de la cola de FX, que es ejecutado asincrónicamente, sin detener la ejecución del programa.

Los efectos se pueden poner en cola de forma secuencial mediante el encadenamiento, pero el otro código se ejecutará independientemente de la ejecución de la cola fx. La forma de obtener el orden de las operaciones de la manera que desea es crear una cola personalizada como lo hizo, o usar las funciones de devolución de llamada para cada efecto.

E.g.

$('#loadingIndicator').show(250,function(){ 
    $('#cases').hide(250,function(){ 
     doSort(columnNumber); 
    }).show(250, function(){ 
     $('#loadingIndicator').hide(250);}) 
}); 

JSFiddle example

ED: Accidentalmente el conjunto de textos.

+0

Gracias por la información. Estoy seguro de que esta información de cola personalizada será útil en el futuro cercano. – Harinder

Cuestiones relacionadas