2010-10-20 40 views
5

Gần đây tôi đã bắt đầu làm việc với jQuery và hôm nay nhận thấy một vấn đề lạ với cách nó hoạt động cho tôi. Như tôi đã hiểu, JavaScript là một luồng đơn. Vì vậy, tất cả các hoạt động của nó nên chạy trong một cơ sở FIFO. Tuy nhiên, đây không phải là trường hợp của tôi. Xin vui lòng xem xét những điều sau đây.jQuery không thực thi đúng thứ tự?

SETUP như sau

HTML:

3 divs

  • div # 1 => chứa các yếu tố tiêu đề có thể được bấm để thực hiện các loại chức năng

  • div # 2 => chứa dữ liệu cần được sắp xếp

  • div # 3 => chứa một .gif cơ bản được sử dụng để thông báo cho người dùng rằng một số hoạt động đang được thực hiện

jQuery - chứa các chức năng sắp xếp mà không thao tác DOM. Về cơ bản, nó đọc dữ liệu từ trang HTML, lưu trữ trong một mảng 2D và sắp xếp mảng. Sau đó nó xóa div # 2 (dữ liệu div) hoàn toàn và xây dựng lại nó, sử dụng dữ liệu từ mảng được sắp xếp.

THỰC HIỆN được dự kiến ​​sẽ thực hiện như sau

  • dùng nhấp vào một trong các tiêu đề để kích hoạt chức năng sắp xếp
  • chức năng sắp xếp ẩn div # 2 và cho thấy div # 3
  • chức năng sắp xếp là được thực hiện
  • khi sắp xếp xong, div # 2 (div dữ liệu) được hiển thị và div # 3 bị ẩn

Tuy nhiên, đây là những gì dường như xảy ra

  • dùng nhấp chuột vào tiêu đề

  • loại xảy ra

  • ẩn và hiển thị của div xảy ra ở bước cuối cùng

Ban đầu, vì tôi không thể thấy bất kỳ div nào được hiển thị/ẩn, tôi đã giả định rằng nó đã xảy ra quá nhanh để tôi chú ý. Vì vậy, tôi đã thêm một sự chậm trễ thời gian vào các hàm .show() và .hide() của jQuery. Một khi điều này đã được thực hiện, nó đã được khá rõ ràng rằng hiển thị và ẩn các hành động đã được thực hiện vào cuối cùng.

* GIẢI PHÁP * Sau nhiều tìm kiếm, tôi đã quản lý để làm việc này như mong đợi bằng cách sử dụng các hàm jQuery .queue() và .dequeue(). Gót chân achilles ở đây là tôi phải chèn một độ trễ 1 mili giây giữa mỗi thao tác. Sau đó và chỉ sau đó là trình duyệt có thể ẩn/hiện divs như tôi muốn.Vì vậy, các hoạt động đã đi một cái gì đó như thế này:

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

}

Tôi chắc chắn không phải là một chuyên gia về vấn đề này, nhưng tôi sẽ nghĩ rằng hoạt động nên được thực hiện theo thứ tự như chúng được gọi. Trình duyệt có hiển thị không đúng thứ tự không? JQuery có thay đổi thứ tự các hoạt động để làm cho mọi thứ hiệu quả hơn không?

Trong khi "giải pháp" thực hiện công việc, tôi không tin rằng đó là giải pháp tốt nhất trong trường hợp này. Có cách nào khác để làm điều này? Nếu cần, tôi có thể cung cấp các ví dụ về mã hoạt động sẽ giải thích vấn đề. Cảm ơn bạn.

Trên một ghi chú khác, tôi đã nhận thấy với tập dữ liệu lớn, khi người dùng nhấp vào yếu tố đầu trang để kích hoạt sắp xếp, trình duyệt sẽ không phản hồi. Tôi nhận ra nó đang thực hiện chức năng sắp xếp, nhưng tôi đã hy vọng sẽ có một cách để tránh điều này. Có suy nghĩ gì không?

Trả lời

7

Các hoạt động đang được thực hiện theo thứ tự mà chúng được gọi, nhưng vấn đề là các phần tử DOM và những gì được hiển thị trên màn hình là hai điều riêng biệt. Quá trình hiển thị các phần tử trên màn hình chạy trong cùng một môi trường luồng đơn như mã Javascript, vì vậy nó không thể hiển thị bất kỳ thay đổi nào trên sceen cho đến khi kịch bản của bạn kết thúc.

Để thay đổi hiển thị, bạn phải kết thúc tập lệnh và sau đó tiếp tục lại khi trình kết xuất đã có cơ hội hiển thị thay đổi.

Bạn có thể sử dụng phương pháp setTimeout để trở về điều khiển trình duyệt, và nhận được phần còn lại của mã để bắt đầu càng sớm càng tốt:

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

window.setTimeout(function(){ 

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

}, 0); 
+0

Tuyệt vời, cảm ơn bạn vì đã giải thích dễ dàng. Tôi hiện đang sử dụng phương pháp này và tôi phải nói nó sử dụng mã khá ít hơn so với phương thức xếp hàng khác mà tôi đã sử dụng. Chúc mừng. – Harinder

1

.show().hide() là thành viên của hàng đợi fx, đó là được thực thi không đồng bộ, không dừng thực hiện chương trình.

Hiệu ứng có thể được xếp hàng tuần tự bằng chuỗi, nhưng mã khác sẽ thực thi độc lập với thực thi hàng đợi fx. Cách để có được thứ tự các hoạt động theo cách bạn muốn là tạo một hàng đợi tùy chỉnh như bạn đã làm, hoặc sử dụng các hàm gọi lại cho mỗi hiệu ứng.

Ví dụ:

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

JSFiddle example

ED: Tôi vô tình toàn bộ từ.

+0

Cảm ơn bạn đã thấu hiểu. Tôi chắc chắn thông tin hàng đợi tùy chỉnh này sẽ có ích trong tương lai gần. – Harinder

Các vấn đề liên quan