2011-10-13 28 views
22

Tôi có một trình xử lý sự kiện, nhưng tôi muốn đảm bảo rằng nó sẽ đợi cho đến khi tất cả các sự kiện khác trong hàng đợi sự kiện đã được thực hiện.Cách chạy mã sau khi tất cả các sự kiện khác đã được xử lý

Ví dụ: tôi có một số tab trên một trang. Tôi có một số mã chung để xử lý các tab đặt tab thành "Tab hoạt động" khi người dùng nhấp vào tab đó.

$('a.tab').click(function() { 
    $(this).parent('div').find('a.tab').removeClass('activeTab'); 
    $(this).addClass('activeTab'); 
}); 

Đối với một tập hợp cụ thể của các tab, tôi có thể có một handler:

// handler-1 
$('div#myTabs a.tab').click(function() { 
    do_something(); 
}); 

function do_something() { 
    var type = $('div#myTabs a.activeTab').data('type'); 
    do_something_else(type); 
} 

do_something() có thể được gọi là để phản ứng lại hành động khác ngoài cách nhấp vào một tab, nhưng bất kể như thế nào được gọi, nó muốn biết tab đang hoạt động là gì trước khi nó có thể tiếp tục.

Vấn đề của tôi là nếu nó được gọi bởi mã dưới '// handler-1', lớp 'activeTab' có thể chưa được đặt lại, vì vậy giá trị nó lấy cho 'loại' sẽ vẫn là từ bất kỳ thẻ nào được chọn trước khi nhấp vào thẻ này.

Tôi giải quyết nó như thế này:

// handler-1 
$('div#myTabs a.tab').click(function() { 
    set_timeout(function() { 
    do_something(); 
    }, 100); 
}); 

này trông giống như quá nhiều của một kludge để thỏa mãn cho tôi. Làm thế nào để tôi biết rằng bộ xử lý sự kiện hẹn giờ sẽ được gọi chỉ sau khi tất cả các trình xử lý khác đã có lượt của họ? Chắc chắn tôi có thể thay đổi "100" thành "1000" hoặc thậm chí "10000" nhưng tôi cũng sẽ có hiệu suất giao dịch cao hơn (và vẫn không chắc chắn vì thậm chí 10 giây có thể không đủ trên một phiên bản trình duyệt trên máy bị tê liệt đủ).

Tôi đã thấy một số giải pháp có thể:

nhưng không ai trong số này đủ nói chung để đáp ứng tôi. Tôi không cố gắng xử lý để chạy trước tiên. Thay vào đó, tôi muốn một cái gì đó như thế này:

function do_something() { 
    $.when_all_other_events_have_been_handled(function() { 
    do_something(); 
    }); 
}); 

Có bất cứ điều gì như thế này tồn tại không?

Tôi đã xem $ .fn.when (arg) .done(), nhưng khi nào? "arg" trong trường hợp này sẽ phải là một đối tượng trì hoãn thực hiện bất cứ điều gì đã có trong hàng đợi chạy. A Catch-22!

Sproutcore có nội dung như "engine.run()" (không nhớ tên chính xác) sẽ chỉ trả về khi tất cả các sự kiện khác trong "công cụ" đã được xử lý, nhưng tôi không thể tìm thấy bất kỳ thứ gì như vậy trong jQuery. (http://api.jquery.com/category/events/). Nếu bất cứ ai biết về một cái gì đó như thế, xin vui lòng cho tôi biết!

Cảm ơn! :)

Trả lời

27

Hãy thử điều này:

function postpone(fun) 
{ 
    window.setTimeout(fun,0); 
} 

vì vậy nếu bạn sẽ gọi postpone(do_something); rằng do_something sẽ được thực hiện sau khi tất cả các sự kiện UI có trong hàng đợi sự kiện cho thời điểm postpone() gọi.

+0

Xin chào! Bạn đánh tôi đến câu trả lời của riêng tôi! –

+1

Tôi đã sử dụng điều này với thời gian chờ tích cực và cho rằng đó là điều kiện chạy đua, vui mừng khi thấy nó hợp lệ :) – Jake

+0

Lỗi phải đối mặt khi sử dụng chức năng trì hoãn: lỗi gọi setTimeout vô dụng (thiếu dấu ngoặc kép xung quanh đối số?) Trong FireFox 20.0 cho Ubuntu chuẩn 1.0. @ Lsiden trả lời đã làm việc cho tôi. –

25

Tôi có thể đã tìm thấy câu trả lời tại đây: http://ejohn.org/blog/how-javascript-timers-work/

Theo J.Resig, nếu tôi làm

setTimeout(function() { 
    do_something(); 
}, 0); 

các chức năng ẩn danh sẽ được enqued ngay lập tức nhưng sẽ không được gọi cho đến khi mọi thứ khác trên hàng đợi sự kiện đã được xử lý. Đó là, miễn là bất cứ trình duyệt nào chạy nó thực sự chạy mọi thứ trên cơ sở đầu tiên-ra-trước-ra như tôi mong đợi. Nếu vì lý do nào đó, công cụ Javascript sẽ tự nó sắp xếp lại các sự kiện trong hàng đợi (tôi không biết tại sao nó nên, nhưng bạn không bao giờ biết vì AFAIK tôi chưa bao giờ thấy bất kỳ sự bảo đảm nào như vậy trong tiêu chuẩn, nhưng sau đó tôi cần phải nhìn lại) thì tất cả mọi phiên cược đều bị tắt!

+0

Hiện không thấy hành vi này với Chrome. Tôi có 2 chức năng riêng biệt được gọi là sự kiện "nhấp" của hộp kiểm. Trên một trong những tôi muốn cuối cùng tôi bọc nó trong setTimeout nhưng nếu tôi đặt nó là 0 .. nó có vẻ là một điều kiện chủng tộc. Tôi đặt nó lên 500 và nó có vẻ hoạt động, nhưng tôi sợ nó chỉ là do may mắn. – Dss

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