2012-01-05 2 views
7

Tôi đã có một trò chơi mà chạy trong trình duyệt web (như là một plugin) và những gì tôi đang cố gắng làm là:Ngăn chặn trình duyệt web từ đóng cửa cho đến khi phản ứng AJAX được trả về

  1. Detect nếu người dùng đã quyết định đóng trình duyệt (Alt + F4, nhấn nút 'X', v.v.)

  2. Ngăn trình duyệt kết thúc khi chúng tôi gọi điện đến các dịch vụ web của chúng tôi để ghi lại rằng người dùng đã đóng trình duyệt

  3. Khi chúng tôi nhận được phản hồi từ các dịch vụ web, thả khóa và cho phép trình duyệt đóng lại theo yêu cầu.

Lý do chính chúng tôi muốn làm điều này là chúng tôi đang gặp phải một số vấn đề đồng thời và duyệt qua nhật ký của mình, chúng tôi muốn cách ly mọi người đăng xuất/đóng trình duyệt khỏi các phiên bản chính hãng.

Tôi nhìn vào thực hiện điều này với JQuery (đối với X-Browser tương thích - Opera sẽ không làm việc nhưng chúng tôi không có bất kỳ người dùng trên Opera nào may mắn):

$(window).bind('beforeunload', function(e) { 
    e.preventDefault(); 
    // make AJAX call 
}); 

Vấn đề là màn hình này hộp thoại xác nhận cho người dùng ('Bạn có chắc chắn muốn thoát khỏi trang này') mà người dùng có thể xác nhận trước khi cuộc gọi AJAX được gửi hay không.

Vì vậy, câu hỏi đặt ra là có cách ngăn trình duyệt đóng lại cho đến khi nhận được phản hồi không? Ngoài ra 'beforeunload' cũng kích hoạt khi trang được thay đổi - có cách nào để phân biệt nhấp vào một liên kết từ thực sự nhấp vào đóng không?

Biết ơn vì bất kỳ trợ giúp nào về điều này!

+0

Chỉ cần ra khỏi tò mò ... là có bất kỳ sự khác biệt nếu bạn trao đổi "preventDefault" và "thực hiện cuộc gọi ajax" phần? – hugomg

Trả lời

6

Hoạt động kinh doanh phức tạp của nó để tránh cửa sổ trình duyệt không bị đóng. Trên thực tế, không có cách nào để làm điều đó, bên cạnh việc trả về giá trị không phải là undefined từ sự kiện onbeforeunload, như bạn đã mô tả.

Có một đề xuất có thể tôi có thể thực hiện, đó là yêu cầu đồng bộ yêu cầu ajax trong sự kiện onbeforeunload. Ví dụ:

window.onbeforeunload = function() { 
    $.ajax({ 
     url: '/foo', 
     type: 'GET', 
     async: false, 
     timeout: 4000 
    }); 
}; 

Về lý thuyết, điều này sẽ chặn trình duyệt trong tối đa 4 giây. Trên thực tế, các trình duyệt sẽ xử lý điều này một cách khác nhau. Ví dụ, Firefox (tôi đã thử nghiệm nó trên 9), thực sự sẽ không đóng cửa sổ ngay lập tức, nhưng nó cũng không tôn trọng giá trị thời gian chờ ở đó. Tôi đoán có tối đa nội bộ là 2 giây trước khi yêu cầu bị hủy và cửa sổ/tab bị đóng. Tuy nhiên, điều đó là đủ trong hầu hết các trường hợp tôi đoán.

Câu hỏi khác của bạn (cách phân biệt giữa nhấp vào liên kết), khá đơn giản. Như được mô tả ở trên, onbeforeunload xem nội dung đang được trả về từ trình xử lý sự kiện của nó.Vì vậy, cho phép giả sử chúng ta có một biến đó là toàn cầu cho các ứng dụng của chúng tôi, chúng tôi có thể làm điều gì đó như

var globalIndicator = true; 

// ... lots of code 

window.onbeforeunload = function() { 
    return globalIndicator; 
}; 

Tại thời điểm này, chúng tôi sẽ luôn luôn nhận được một hộp thoại xác nhận khi cửa sổ/tab sắp bị đóng cửa. Nếu chúng ta muốn tránh điều đó cho bất kỳ neo nhấp chuột, chúng ta có thể vá nó như

$('a[href^=http]').on('click', function() { 
    globalIndicator = undefined; 
}); 
+0

Cảm ơn Andreas về đầu vào của bạn; do đó, thực sự không có cách nào để ngăn trình duyệt đóng lại cho đến khi nhận được phản hồi ... vấn đề là nếu người chơi đang kết nối chậm; 2 giây có thể không đủ dài để thực hiện cuộc gọi. Cảm ơn bạn đã giải thích về cách phân biệt giữa việc nhấp vào liên kết - hữu ích nhất – csdev86

+0

Nếu bạn nghĩ về cách sử dụng liên kết, rõ ràng là không có trình duyệt nào cho phép trang chặn trong một thời gian dài tùy ý trước khi đóng. Nếu có thể, ai đó có thể, ví dụ: tạo quảng cáo bật lên mà người dùng không bao giờ có thể đóng. – smorgan

0

Tôi khá chắc chắn rằng những gì bạn muốn là không thể sử dụng JavaScript. Nhưng kể từ khi bạn có một plugin trình duyệt, bạn không nên kiểm tra xem đối tượng plugin của bạn đã được dọn dẹp chính xác chưa? Tôi không chắc liệu bạn đang sử dụng ActiveX, NPAPI hay cái gì đó như Firebreath, nhưng những khung công tác này đều có các phương thức vòng đời sẽ được gọi trên plugin của bạn trong trường hợp tắt máy bình thường, vì vậy bạn có thể viết một cái gì đó cho nhật ký tại thời điểm này. Nếu plugin bị lỗi, chúng sẽ không được gọi.

+0

Thực tế chúng tôi không thể thực hiện cuộc gọi từ plugin một cách đáng tin cậy là lý do tại sao bắt đầu xem xét việc thực hiện nó từ trình duyệt web. – csdev86

1

Đối với phần đầu của câu hỏi của bạn, không có cách nào đáng tin cậy của ngăn trình duyệt đóng khác vì sử dụng window.onbeforeunload. Trình duyệt có sẵn để phục vụ người dùng và nếu người dùng chọn đóng trình duyệt của mình thì trình duyệt sẽ làm như vậy.

Đối với câu hỏi thứ hai của bạn, nó là khá dễ để phân biệt một nhấp chuột vào một liên kết từ các sự kiện khác gây ra một sự kiện onbeforeunload bởi jQuery:

$('a').click(function(e) {...}); 

Bạn có thể sử dụng này, ví dụ, để đảm bảo một nhấp chuột sẽ không kích hoạt unbeforeunload:

$('a').click(function(e) {window.onbeforeunload = null}); 
1

Bạn có thể sử dụng mã dưới đây để ngăn chặn trình duyệt khỏi bị đóng cửa: -

window.onbeforeunload = function() { 

//Your code goes here. 

    return ""; 
} 

Bây giờ, khi người dùng đóng trình duyệt thì anh ta nhận được cuộc đối thoại xác nhận vì trả lại ""; & chờ xác nhận của người dùng & thời gian chờ này sẽ yêu cầu đến máy chủ.