2010-06-29 39 views
31

Về cơ bản, khi người dùng rời khỏi trang web trong ứng dụng của tôi, tôi cần gọi một tập lệnh PHP bằng AJAX, sẽ chèn thời gian vào trang web vào cơ sở dữ liệu và sau đó rời khỏi trang. Điều quan trọng là phải đợi yêu cầu AJAX kết thúc vì các trang web trong ứng dụng của tôi không thể truy cập được đối với người dùng trừ khi họ đã dành thời gian nhất định trên trang trước (giả sử hai phút).

Đây là mã jquery của tôi:

$(document).ready(function() { 

    var teid = TEID; 
    var startTime = new Date().getTime(); 

    $(window).unload(function() { 
     var timeSpentMilliseconds = new Date().getTime() - startTime; 
     var t = timeSpentMilliseconds/1000/60; 

     $.ajax({ 
      type: 'POST', 
      url: '/clientarea/utils/record-time', 
      data: 'teid=' + teid + '&t=' + t 
     }); 
    }); 

}); 

Làm thế nào tôi nên thay đổi nó để nó sẽ đợi cho yêu cầu AJAX để chấm dứt trước khi rời khỏi trang web?

EDIT:

Hoặc có thể tốt hơn (dễ dàng hơn) để chỉ yêu cầu AJAX được lặp lại sau mỗi phút. Điều đó có thể không?

Trả lời

30

Vâng, bạn có thể đặt async: false trong cuộc gọi AJAX để làm cho trình duyệt chờ yêu cầu hoàn tất trước khi thực hiện bất kỳ điều gì khác, nhưng lưu ý rằng điều này sẽ 'treo' trình duyệt trong suốt thời gian yêu cầu.

$.ajax({ 
    type: 'POST', 
    async: false, 
    url: '/clientarea/utils/record-time', 
    data: 'teid=' + teid + '&t=' + t 
}); 

Từ hướng dẫn:

Theo mặc định, tất cả các yêu cầu được gửi không đồng bộ (ví dụ này được thiết lập là true theo mặc định). Nếu bạn cần các yêu cầu đồng bộ, hãy đặt tùy chọn này thành false. Yêu cầu miền chéo và kiểu dữ liệu: yêu cầu "jsonp" không hỗ trợ thao tác đồng bộ. Lưu ý rằng các yêu cầu đồng bộ có thể tạm thời khóa trình duyệt, vô hiệu hóa bất kỳ hành động nào trong khi yêu cầu đang hoạt động.

+0

Hmm. Cảm ơn. Tôi đã cập nhật câu hỏi của mình. Nó có thể được dễ dàng hơn để chỉ cần cho phép AJX lặp lại mỗi phút chúng ta hãy nói. Tôi sẽ làm như thế nào? –

+12

Tôi đặc biệt khuyên bạn nên tránh điều đó, ** đặc biệt ** trên 'unload'. – jAndy

+0

Tôi đã tìm thấy luôn luôn có một giải pháp tốt hơn so với làm 'async: false', bất kể vấn đề. –

4

đối với tôi, bạn không phải là một ý tưởng tốt cho trình duyệt để chờ đợi trước khi đóng cửa ...
đơn giản chỉ vì những gì nếu tôi thực sự muốn đóng nó? ...

nếu một trang làm phiền người dùng, không tốt ...

đề xuất của tôi là, trong trang, bạn đợi 2 phút (nếu 2 phút là yêu cầu), sau đó gửi ajax mà người dùng đã thực hiện 2 phút của mình ...

bạn có thể kiểm tra xem ở phía máy chủ nếu có có 2 phút của anh ấy hay không ...

0

Phương thức jQuery.ajax() có tùy chọn async. Nếu bạn đặt nó thành false, cuộc gọi sẽ chặn cho đến khi phản hồi quay lại (hoặc nó đã hết thời gian chờ). Tôi khá shure, mà gọi này, sẽ yause trình duyệt để weit trong xử lý unload.

Lưu ý phụ: Bạn không thể dựa vào tính năng này để hoạt động. Nếu trình duyệt cung cấp cho người dùng tùy chọn hủy các trình xử lý tải (mà một số trình duyệt thực hiện sau một thời gian chờ), thì "thời gian trên trang web" sẽ không bao giờ được cập nhật. Bạn có thể thêm bộ hẹn giờ vào trang web, định kỳ gọi một tập lệnh trên máy chủ và cập nhật thời gian. Bạn sẽ không có giá trị chính xác, nhưng trong trường hợp của bạn, điều này là không cần thiết.

Nếu bạn chỉ cần biết liệu người dùng có X giây trên trang Bạn chỉ có thể đặt thời gian chờ trong trình xử lý tải (sử dụng setTimeout(function, ms)) thực hiện cuộc gọi nếu người dùng đã dành thời gian cần thiết. Vì vậy, sẽ không cần một trình xử lý không tải.

1

sử dụng onbeforeunload:

$(document).ready(function(){ 
    window.onbeforeunload = function(){ 
    // $.ajax stuff here 
    return false; 
    } 
}); 

này ít nhất sẽ mang lại cho người dùng một messagebox mà hỏi anh ta nếu anh ta muốn để đóng cửa sổ hiện tại/tab.

1

Tôi nghĩ sẽ tốt hơn nếu bạn sử dụng kỹ thuật bỏ phiếu như bạn đề xuất, mặc dù nó sẽ gây ra một số tải trên máy chủ web.

$(document).ready(function() { 

    var teid = TEID; 
    var startTime = new Date().getTime(); 

    var ajaxFunc = function() { 
     var timeSpentMilliseconds = new Date().getTime() - startTime; 
     var t = timeSpentMilliseconds/1000/60; 

     $.ajax({ 
      type: 'POST', 
      url: '/clientarea/utils/record-time', 
      data: 'teid=' + teid + '&t=' + t 
     }); 
    }; 

    setInterval(ajaxFunc, 60000); 

}) 

Bạn sẽ được vui mừng khi bạn có thể sử dụng WebSockets :)

+0

Cảm ơn. Nhưng điều này sẽ chỉ được thực hiện sau một phút? Nó có thể thực thi liên tục mỗi phút (60 giây) không? –

+2

Đó là những gì setInterval làm, trái ngược với setTimeout – sje397

2

Đó là một ý tưởng tồi để thử và chiếm quyền điều khiển trình duyệt của người dùng, vì nó sẽ cung cấp cho họ một cảm giác xấu và gửi chúng đi.

Nếu vì một lý do nào đó bạn không muốn tạo trang mới cho đến khi người dùng dành thời gian tối thiểu cho trang trước đó, điều tốt nhất cần làm là phía máy chủ thí điểm, tức là chuyển hướng đến trang hiện tại cho đến thời gian được yêu cầu đã đạt.

Bạn thậm chí không cần thực hiện cuộc gọi ajax, chỉ lưu trữ trong phiên dấu thời gian khi trang được phân phối và không hiển thị trang sau cho đến khi một khoảng thời gian nhất định trôi qua.

Hãy chắc chắn thông báo cho người dùng rằng họ phải đợi trang mới sẵn sàng, có thể với đếm ngược javascript đơn giản.

Nếu bạn muốn người dùng thực sự có trang hoạt động trong một khoảng thời gian nhất định (tức là không chuyển sang một tab/cửa sổ khác chờ hai phút trôi qua), tôi không thể đề xuất một giải pháp hiệu quả.

6

Làm thế nào về việc đặt cookie trong trình xử lý tải chưa? Máy chủ sẽ nhìn thấy nó trên các yêu cầu tiếp theo.

<script> 
    $(window).unload(function(){document.cookie='left_on='+(new Date())}) 
</script> 
7

Giải pháp tốt nhất là sử dụng navigator.sendBeacon. Đây là chức năng hoàn toàn mới bắt đầu được triển khai trong các phiên bản mới của trình duyệt. Chức năng này có sẵn trong các trình duyệt mới hơn Chrome 39 và Firefox 31. Nó không được Internet Explorer và Safari hỗ trợ tại thời điểm viết. Để đảm bảo yêu cầu của bạn được gửi trong các trình duyệt chưa hỗ trợ chức năng mới, bạn có thể sử dụng giải pháp này:

var navigator.sendBeacon = navigator.sendBeacon || function (url, data) { 
    var client = new XMLHttpRequest(); 
    client.open("POST", url, false); // third parameter indicates sync xhr 
    client.setRequestHeader("Content-Type", "text/plain;charset=UTF-8"); 
    client.send(data); 
}; 

Hy vọng điều này sẽ hữu ích!

+0

Tôi nghĩ rằng đây là thanh lịch, tôi đã sử dụng nó trong Electron để gửi dữ liệu khi ứng dụng được đóng – furiel

+0

Năm 2018, đây là con đường để đi. – Baishu

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