js監聽瀏覽器關閉事件(區分重新整理和關閉,相容IE9,10,11,Edge,Chrome和Firefox)
阿新 • • 發佈:2018-11-06
由於各瀏覽器相容性不同,所以首先要先區分各瀏覽器
var userAgent = navigator.userAgent; //取得瀏覽器的userAgent字串 var isOpera = userAgent.indexOf("Opera") > -1; //判斷是否Opera瀏覽器 var isIE = userAgent.indexOf("compatible") > -1 && userAgent.indexOf("MSIE") > -1 && !isOpera; //判斷是否IE瀏覽器 var isIE11 = userAgent.indexOf("rv:11.0") > -1; //判斷是否是IE11瀏覽器 var isEdge = userAgent.indexOf("Edge") > -1 && !isIE; //判斷是否IE的Edge瀏覽器
1.chrome和FireFox
if(!isIE && !isEdge && !isIE11) {//相容chrome和firefox var _beforeUnload_time = 0, _gap_time = 0; var is_fireFox = navigator.userAgent.indexOf("Firefox")>-1;//是否是火狐瀏覽器 window.onunload = function (){ _gap_time = new Date().getTime() - _beforeUnload_time; if(_gap_time <= 5){ $.post('webLoginController.do?delSession2');//瀏覽器關閉 }else{//瀏覽器重新整理 } } window.onbeforeunload = function (){ _beforeUnload_time = new Date().getTime(); if(is_fireFox){//火狐關閉執行 $.post('webLoginController.do?delSession2');//瀏覽器關閉 } }; }
2.IE9, 10,11,Edge
這四個瀏覽器可以用beforeUnload事件監聽瀏覽器關閉,但是無法區分重新整理和關閉。所以我是用如下方法解決的:
思路:
IE9和10
這兩個瀏覽器在重新整理時先觸發beforeunload事件,再觸發unload事件。而在關閉時只觸發beforeunload事件。所以根據這個特點。在beforeunload時呼叫A方法,將"1"存入session的"flagiii"屬性中,並單開一個執行緒延遲一段時間執行B,在unload時再呼叫C將"flagiii"屬性的值改為0;這樣,在A中延遲一段時間後判斷session中的flagiii屬性的值是否為1,為1的話則是關閉,呼叫B方法(來操作你要操作的事情(我要做的是刪除庫中的內容和session))。為0是重新整理,不呼叫B方法。
js:
if(isIE) {//相容ie8,9,10
window.onbeforeunload = function() {
//alert(0);
flagiii = "1";
$.ajax({
type: "post",
url: "webLoginController.do?A",
data:{"flagiii": flagiii},
success: function() {
},
async:false
});
}
window.onunload = onclose;
function onclose(){
flagiii = "0";
$.ajax({
type: "post",
url: "webLoginController.do?storageData",
data:{"flagiii": flagiii},
success: function() {
}
});
}
}
java:
/**
* 關閉瀏覽器時清除session相容IE9和IE10瀏覽器
* 讓方法延遲10s執行
* create by lucy
* 2017-12-19
*/
@RequestMapping(params = "A")
public void A(
@RequestParam("flagiii") String flagiii,
final HttpSession session,
final HttpServletRequest req
) {
session.setAttribute("flagiii", flagiii);
Thread thread = new Thread(new Runnable(){
@Override
public void run() {
System.out.println("begin");
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("end");
delData(session, req);
}
});
thread.start();
}
public void B(HttpSession session,HttpServletRequest req) {
String flagiii = (String) session.getAttribute("flagiii");
if("1".equals(flagiii)) {
boolean isTrue = false;
String userId = session.getAttribute("userId").toString();
isTrue = webLoginService.deleteOnline(userId);
//將安全日誌插入資料庫 map
SafeLogInsertDBUtils.safeLogInsertDB(req, session, "關閉瀏覽器", true,StringUtil.LOGINOUT);
}
}
/**
* 儲存標記(配合delSessionData方法)
* @param flagiii
* create by lucy
* 2017-12-19
*/
@RequestMapping(params = "B")
public void B(
HttpSession session,
@RequestParam("flagiii") String flagiii
) {
session.setAttribute("flagiii", flagiii);
}
IE11和Edge
思路類似於9和10,IE11和Edge瀏覽器在關閉時先觸發beforeunload,然後再觸發unload事件。而重新整理時先觸發beforeunload事件,再觸發unload事件,再觸發load事件。所以先在頁面load後將"0"存入session,在beforeunload中存入"1"在unload事件中呼叫方法,開啟一個新執行緒,延遲10s執行你想做的事。
js:
var flagiii = "0";
function onloadFun() {
$.ajax({
type: "post",
url: "webLoginController.do?storageData",
data:{"flagiii": flagiii},
success: function() {
}
});
}
if(isIE || isIE11 || isEdge) {
//頁面載入進來後將flagii存入session
onloadFun();
}
if(isIE11 || isEdge) {//相容ie11 edge
window.onbeforeunload = function() {
flagiii = "1";
$.ajax({
type: "post",
url: "webLoginController.do?storageData",
data:{"flagiii": flagiii},
success: function() {
},
async:false
});
}
window.onunload = onclose;
function onclose(){
$.ajax({
type: "post",
url: "webLoginController.do?delSessionData",
data: {"rnd": Math.random()},
success: function() {
}
});
}
}
java:
/**
* 儲存標記(配合delSessionData方法)
* @param flagiii
* create by lucy
* 2017-12-19
*/
@RequestMapping(params = "storageData")
@ResponseBody
public void storageData(
HttpSession session,
@RequestParam("flagiii") String flagiii) {
session.setAttribute("flagiii", flagiii);
}
/**
* 關閉瀏覽器時清除session相容IE11和Edge瀏覽器
* 讓方法延遲30s執行
* create by lucy
* 2017-12-19
*/
@RequestMapping(params = "delSessionData")
@ResponseBody
public void delSessionData(final HttpSession session, final HttpServletRequest req) {
Thread thread = new Thread(new Runnable(){
@Override
public void run() {
System.out.println("begin");
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("end");
delData(session, req);
}
});
thread.start();
}
注意: 在beforeunload事件中的ajax請求使用同步(async: false),否則無法傳送。