2010-02-03 27 views
5

Tôi có một cuộc gọi Ajax hiện cần phải đồng bộ. Tuy nhiên, trong khi cuộc gọi Ajax này đang thực thi, giao diện trình duyệt bị đóng băng, cho đến khi cuộc gọi trả về. Trong trường hợp hết thời gian chờ, điều này có thể đóng băng trình duyệt cho một số significant period of time.Có thể tải cửa sổ trình duyệt khi đang trong vòng lặp Javascript không?

Có cách nào để trình duyệt (bất kỳ trình duyệt nào) làm mới giao diện người dùng, nhưng không thực thi bất kỳ Javascript nào không? Lý tưởng nhất nó sẽ là một số lệnh như window.update(), mà sẽ cho phép làm mới giao diện người dùng thread.

Nếu đây sẽ có thể, sau đó tôi có thể thay lời gọi AJAX đồng bộ với một cái gì đó như:

obj = do_async_ajax_call(); 
while (!obj.hasReturned()) { 
    window.update(); 
} 
// synchronous call can resume 

Lý do mà tôi không thể sử dụng setTimeout, hoặc tiếp tục một hàm trong khi gọi lại, đó là dòng chảy thực hiện không thể bị gián đoạn: (có quá nhiều biến trạng thái mà tất cả phụ thuộc vào nhau, và dòng chảy long_function() nếu không sẽ phải được nối lại bằng cách nào đó):

function long_function() { 
    // lots of code, reads/writes variable 'a', 'b', ... 
    if (sync_call_is_true()) { 
    // lots of code, reads/writes variable 'a', 'b', ... 
    } else { 
    // lots of code, reads/writes variable 'a', 'b', ... 
    } 
    // lots of code, reads/writes variable 'a', 'b', ... 
    return calculated_value; 
} 
+2

Tại sao cuộc gọi cần phải đồng bộ? –

+1

Bạn có thể đăng toàn bộ mã cuộc gọi không? Điều này có thể có thể được đơn giản hóa và sử dụng các chức năng XHR để hỗ trợ những gì bạn cần (trừ khi jQuery là một tùy chọn, sau đó thậm chí còn sạch hơn). Nếu không phải là một tùy chọn, tôi yêu cầu bạn đổi tên hàm thành 'do_sync_jax_call(); ' –

Trả lời

3

Bạn cần phải thay thế yêu cầu đồng bộ của bạn với một yêu cầu không đồng bộ và sử dụng gọi lại. Ví dụ đơn giản sẽ là:

obj = do_async_ajax_call(function (data, success) 
{ 
    if (success) 
    { 
     // continue... 
    } 
}); 

function do_async_ajax_call(callback) 
{ 
    var xhr = new XMLHttpRequest(); 
    xhr.open("GET", "http://mysite.com", true); 
    xhr.onreadystatechange = function() 
    { 
     if (xhr.readyState == 4 && xhr.status == 200) 
      callback(xhr.responseXML, true); 
     else if (xhr.readyState == 4) 
      callback(null, false); 
    } 
    xhr.send(); 
} 

Bằng cách này, bạn đang chuyển một hàm ẩn danh làm tham số cho hàm yêu cầu ajax. Khi ajax hoàn thành, hàm được truyền đi được gọi với responseXML được truyền cho nó. Trong khi chờ đợi, trình duyệt đã được tự do làm điều bình thường cho đến khi cuộc gọi kết thúc. Từ đây, phần còn lại của mã của bạn tiếp tục.

+0

Điều này thường là đủ, nhưng tôi không thể phân chia luồng hoạt động (như được cập nhật trong câu hỏi). Tôi đang thử cách tiếp cận khác ngay bây giờ ... – jevon

+0

Đó là * luôn luôn * có thể chia nhỏ nó; đây là biến đổi CPS (tra cứu "kiểu chuyển tiếp tiếp tục"; tham số tiếp tục là gọi lại của bạn). Các biến trạng thái cục bộ của bạn được đóng đơn giản trong hàm gọi lại. Vòng lặp trở thành cuộc gọi đệ quy. Nó không phải là khó hoặc tối nghĩa một khi bạn nhận được hang của nó. –

+0

Tôi đồng ý nó luôn luôn có thể, nhưng trong trường hợp này nó không phải là giải pháp tốt nhất (có quá nhiều biến trạng thái!) :) Cuối cùng, tôi đã sử dụng kết quả của cuộc gọi lại trước đó (hoặc máy chủ thường xuyên bỏ phiếu) để cập nhật máy khách -side với giá trị được lưu trữ của cuộc gọi đồng bộ khi cần thiết, vì vậy nó không cần phải gọi Ajax cả. – jevon

0

Lấy phần còn lại của cuộc gọi và đặt nó trong cuộc gọi lại được gọi khi kết quả trả về. Tôi nghiêm túc nghi ngờ rằng điều này sẽ là hoàn toàn không thể cho bạn để làm. Bất kỳ logic bạn cần phải đặt trong các cuộc gọi có thể được lặp lại ở các callback

0

ajax không đồng bộ lấy sau đó setTimeout và làm công việc chế biến trong khối (kích hoạt bởi các callback)

0

JavaScript là một chuỗi. Vì vậy, theo định nghĩa, bạn không thể cập nhật giao diện người dùng trong khi bạn đang ở trong một vòng lặp thủy triều. Tuy nhiên, bắt đầu từ Firefox 3.5 có thêm hỗ trợ cho JavaScripts đa luồng được gọi là công nhân web. Công nhân web không thể ảnh hưởng đến giao diện người dùng của trang, nhưng họ cũng sẽ không chặn các cập nhật của giao diện người dùng. Nhân viên của chúng tôi cũng được Chrome và Safari hỗ trợ.
Vấn đề là, ngay cả khi bạn di chuyển cuộc gọi AJAX của mình thành chuỗi nền và chờ thực hiện để hoàn thành, người dùng sẽ có thể nhấn nút và thay đổi giá trị trên giao diện người dùng của bạn (và theo tôi hiểu, đó là những gì bạn cố gắng tránh). Điều duy nhất tôi có thể đề xuất để ngăn chặn người dùng gây ra bất kỳ thay đổi nào là một spinner sẽ chặn toàn bộ giao diện người dùng và sẽ không cho phép bất kỳ tương tác nào với trang cho đến khi cuộc gọi web trở lại.

+0

Tôi không ngại nếu người dùng tương tác với trang (và tương tác được xếp hàng đợi); nhưng hiện tại, trong khi một cuộc gọi Ajax đồng bộ đang thực thi trong Firefox, toàn bộ trình duyệt bị đóng băng. Đây là những gì tôi muốn ngăn chặn. – jevon

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