2010-10-20 15 views
5

Niedawno zacząłem pracować z jQuery i dziś zauważyłem dziwny problem z jego zachowaniem. Jak rozumiem, JavaScript jest pojedynczy wątek. Więc wszystkie te operacje powinny działać w oparciu o FIFO. Jednak nie wydaje mi się, że tak jest. Proszę wziąć pod uwagę następujące kwestie.jQuery nie wykonuje się we właściwej kolejności?

USTAWIENIA jest następujący

HTML:

3 DIV

  • div # 1 => zawiera elementy nagłówka, które można kliknąć, aby wykonać funkcję sortowania

  • div # 2 => zawiera dane, które należy posortować

  • div # 3 => zawiera podstawowe .gif, który jest wykorzystywany do powiadamiania użytkownika, że ​​niektóre operacja jest wykonywana

jQuery - zawiera funkcję sortowania który robi manipulacji DOM. Zasadniczo odczytuje dane ze strony HTML, przechowuje w tablicy 2D i sortuje tablicę. Następnie całkowicie usuwa div # 2 (div danych) i odbudowuje go, używając danych z posortowanej tablicy. Oczekuje

WYKONANIE była następująca

  • użytkownik kliknie jeden z nagłówków do wywołania funkcji sortowania
  • funkcja sortowania ukrywa div # 2 i pokazuje div # 3
  • funkcja sortowania wykonany
  • raz sortowania jest zakończona, div # 2 (div danych) jest pokazany i div # 3 jest ukryte

Jednak tutaj jest to, co wydaje się zdarzyć

  • użytkownik kliknie nagłówki

  • rodzaj występuje

  • Ukrywanie i pokazywanie div dzieje się w ostatnim etapie

Początkowo, ponieważ nie mogłem zobaczyć żadnych div pokazanych/ukrytych, założyłem że działo się to zbyt szybko, abym mógł to zauważyć. Więc dodałem opóźnienie do funkcji .show() i .hide() jQuery. Kiedy już to zrobiono, było całkiem oczywiste, że działania pokazujące i ukrywające zostały wykonane na samym końcu.

* ROZWIĄZANIE * Po długich poszukiwaniach udało mi się uzyskać tej pracy, jak się spodziewałem za pomocą jQuery .queue() i .dequeue (funkcji). Piętą achillesową było to, że musiałem wstawić 1 milisekundę opóźnienia między każdą operacją. Wtedy i tylko wtedy przeglądarka była w stanie ukryć/pokazać div, tak jak chciałem.Więc operacje poszedł coś takiego:

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

}

pewno nie jestem ekspertem w tej dziedzinie, ale myślę, że operacje powinny być wykonywany w tej samej kolejności, jak są one nazywane. Czy przeglądarka nie renderuje się we właściwej kolejności? Czy jQuery zmienia kolejność operacji, aby były bardziej wydajne?

Podczas gdy "rozwiązanie" spełnia swoją funkcję, nie jestem przekonany, że jest to najlepsze rozwiązanie w tym scenariuszu. Czy jest jakiś inny sposób na zrobienie tego? W razie potrzeby mogę podać przykłady kodu pracy, które pokażą problem. Dziękuję Ci.

Z innej notatki zauważyłem w przypadku dużych zestawów danych, gdy użytkownik kliknie element nagłówka, aby uruchomić sortowanie, przeglądarka przestanie odpowiadać. Rozumiem, że wykonuje on funkcję sortowania, ale miałem nadzieję, że będzie sposób, aby tego uniknąć. jakieś pomysły?

Odpowiedz

7

Operacje są wykonywane w tej samej kolejności, w jakiej są wywoływane, ale problem polega na tym, że elementy DOM i to, co widać na ekranie, to dwie osobne rzeczy. Proces renderujący elementy na ekranie działa w tym samym środowisku z pojedynczym wątkiem co kod JavaScript, więc nie może pokazać żadnych zmian na scerze, dopóki skrypt się nie zakończy.

Aby wyświetlić zmiany, należy zakończyć skrypt, a następnie wznowić go, gdy mechanizm renderujący ma szansę wyświetlić zmiany.

Można użyć metody setTimeout aby zwrócić sterowanie do przeglądarki, a resztę kodu, aby rozpocząć jak najszybciej:

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

window.setTimeout(function(){ 

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

}, 0); 
+0

Niesamowite, dziękuję za łatwe do zrozumienia wyjaśnienie. Używam teraz tej metody i muszę powiedzieć, że używa ona nieco mniej kodu niż inna metoda kolejki, której używałem. Twoje zdrowie. – Harinder

1

.show() i .hide() są członkami kolejce FX, który jest wykonywane asynchronicznie, bez zatrzymywania wykonywania programu.

Efekty mogą być kolejkowane w kolejce przez łańcuch, ale inny kod będzie wykonywany niezależnie od wykonania kolejki fx. Aby uzyskać kolejność operacji w żądany sposób, należy utworzyć niestandardową kolejkę, tak jak to zrobiliśmy, lub użyć funkcji wywołania zwrotnego dla każdego efektu.

E.g.

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

JSFiddle example

ED: I przypadkowo całe słowo.

+0

Dziękuję za wgląd. Jestem pewien, że ta niestandardowa informacja o kolejce będzie przydatna w najbliższej przyszłości. – Harinder

Powiązane problemy