瀏覽器重新整理頁面/關閉頁面時,使用jquery+ajax儲存資料的方法
最近做個人專案的時候,有一個需求:使用者在頁面進行各種編輯操作,但是卻不必顯示的儲存修改,下次開啟頁面時依然可以看到修改後的內容。
看到這個需求第一反應就是,前端無感知,後端自動儲存修改。具體怎麼做呢?我的思路是:
1、在前端有修改時,寫一個jquery函式(命名為:storeChange)——通過ajax將修改的內容傳輸到後端,由後端進行操作,比如儲存資料庫等。下次訪問時,從資料庫讀取資料。
2、為了防止使用者在重新整理/關閉頁面不丟失資料,因此需要通過jquery在這兩個事件的時候呼叫storeChange函式。
第一個版本程式碼如下:
//頁面關閉時呼叫
$(window).unload(function ()
{
storeChange();
});
//頁面重新整理時呼叫
$(window).on('beforeunload', function(event) {
storeChange();
});
//前端頁面內容修改觸發
function haveModified()
{
//做一些事情
storeChange();
}
function storeChange()
{
//做一些事情
$.ajax({
type:"POST",
dataType:"json",
data:{projectId:projectId,projectLists:arrProjectNodes},
url:'Project/Project/modifyProject' ,
success:function (data) {
if (data.errno == 0) {
//do something
} else {
console.log('there are some errors in project.js:storeChange ajax' + data.errno + ': ' + data.msg);
}
},
error:function (er) {
console.log('some error in project.js:storeChange ajax' );
}
});
}
但是經檢驗這個版本有諸多問題:
第一、也是最嚴重的就是在重新整理和關閉頁面的時候,經常丟失資料(chrome)甚至部分瀏覽器完全不起作用(遨遊-極速模式,相容模式未試,這裡不是黑遨遊瀏覽器,本人是遨遊瀏覽器的忠實使用者,從初中用到現在,十多年了,個人感覺還是非常好用的);
第二、如果操作非常頻繁,會頻繁呼叫後端介面,浪費資源、加大後端壓力。
因此針對這兩個問題進行解決,方案如下:
針對第一個問題:
【原因】
由於ajax預設是非同步呼叫,這樣就有一個問題:document的內容是先被銷燬,還是先被傳輸到後端?如果是後者則符合專案需求,而如果是前者就會出現問題。
【解決方案】
將重新整理和關閉頁面時呼叫的storeChange函式中的ajax改為同步方式。
針對第二個問題:
【原因】
每一個修改(會點選一些按鈕等進行新增、刪除、編輯等)意味著監聽修改的函式都會被呼叫。
【解決方案(前端)】
設定定時器,預設每過10秒呼叫一次storeChange函式來非同步請求後端介面,這樣可以減少請求次數,而且對於覆蓋型(後面的修改會將前面的修改覆蓋掉,實際上只儲存後面的修改即可)的編輯,效果最好。
【解決方案(後端)】
這裡就不具體討論後端的解決方案了,大體思路就是快取/訊息佇列等。本文只看前端解決方案。
【具體實現】
上述前端的解決方案並不完整,單純使用定時器不能滿足我們的需求,因為多次修改(10秒內)會產生多個定時器,因此需要設定一個cookie來記錄是否被修改,如果被修改,清除上一次的定時器,重新計時。(提醒,使用cookie需要引入jquery對應的檔案)
針對以上兩個問題,修改後的程式碼如下:
//頁面關閉時呼叫
$(window).unload(function()
{
storeChangeRealTime();
});
//頁面重新整理時呼叫
$(window).on('beforeunload', function(event) {
storeChangeRealTime();
});
//前端頁面內容修改觸發
var timerId = null;//記錄定時器名稱
function haveModified()
{
//做一些事情
$.cookie('projectlist_modify_flag', 1);//重新設定cookie,1表示:有修改
//定時器
clearTimeout(timerId);//清除之前的定時器(為了重新計時,否則會有多個定時器同時進行,傳遞多次資料)
timerId = setTimeout(storeChangeDelay, 10000);//設定定時器
}
function storeChangeDelay()
{
//做一些事情
$.ajax({
type:"POST",
dataType:"json",
data:{projectId:projectId,projectLists:arrProjectNodes},
url:'Project/Project/modifyProject',
success:function (data) {
if (data.errno == 0) {
$.cookie('projectlist_modify_flag', 0);//修改的內容已經儲存,將該cookie置為0
} else {
console.log('there are some errors in project.js:storeChange ajax' + data.errno + ': ' + data.msg);
}
},
error:function (er) {
console.log('some error in project.js:storeChange ajax');
}
});
}
function storeChangeRealTime()
{
//做一些事情
$.ajax({
async:false,//這是與storeChangeDelay不同的地方,表示使用同步方式傳輸資料
type:"POST",
dataType:"json",
data:{projectId:projectId,projectLists:arrProjectNodes},
url:'Project/Project/modifyProject',
success:function (data) {
if (data.errno == 0) {
$.cookie('projectlist_modify_flag', 0);//修改的內容已經儲存,將該cookie置為0
} else {
console.log('there are some errors in project.js:storeChange ajax' + data.errno + ': ' + data.msg);
}
},
error:function (er) {
console.log('some error in project.js:storeChange ajax');
}
});
}
程式碼是精簡過的,只是提供個解決這類問題的思路。
PS:當然,這種方法還是有弊端的,比如在重新整理頁面時,由於使用的是ajax同步方式,因此資料量過大或連線慢的話,可能會造成卡頓、甚至假死。如有更好方法請告知,將不勝感激。
水平有限,歡迎指正~
如需轉發,請註明出處,3q~