ajax好處不用多說,如有:非同步載入,實現局部重新整理,提高使用者體驗,等等。
在用ajax做資料提交時,發現一個問題。每次提交之後,更新提示資訊總是出現上一次的更新提示記錄。
手動清理瀏覽器緩衝之後,好像問題可以解決了。可是提交一次之後,第二次又是同樣的問題。
下面看一下我做的一個小程式
做了一個小的網路投票程式,用ajax提交前台的投票資料給後台資料庫。
問題要求簡單描述如下:程式內部要求做好判斷和提示,如果同一天內同一個IP只能限制投票一次;
如果第一次提交,則彈出“投票成功;第二次提交如果同一個主題已經存在的IP不能再次投票,則提示“不能重複投票”。
問題描述之後,似乎很簡單了。
前台HTML提交的js指令碼如下:
function submitVote(obj){ var eve=getEvent(); var chr=document.getElementsByName("netvote"); var count=0; var selList=""; for(var i=0;i<chr.length;i++){ if(chr[i].checked){ count++; selList+=chr[i].value+","; } } if (count<1){ alert("還沒有選擇"); if(eve.preventDefault){eve.preventDefault();} else{eve.returnValue=false;} return false; } var postUrl="/ashx/Vote.ashx?Id="+obj+"&optionId="+selList Request.sendGET(postUrl, cackbackResult,null,null,null);}function cackbackResult(req){ var str=req.responseText; if(str=="0")//如果沒有選擇選項 { alert("沒有選擇"); return false; } if(str=="001")//已經投過的 { alert("已經投過不能重複投票"); return false; } if(str=="002") { alert("投票成功"); location.href='default.html'; }}幕後處理代碼: public void ProcessRequest(HttpContext context) { context.Response.ContentType = "text/plain"; int QId = Gain.GetQueryInt("Id", 0);//問題編號 string optionId = Gain.GetQueryString("optionId"); if (string.IsNullOrEmpty(optionId)) { context.Response.Write("0");//沒有選項 } else if (QId > 0) { try { EEY.Lib.BLL.VoteIp bvIp = new EEY.Lib.BLL.VoteIp(); string Ip = Gain.GetUserIP; string strWhere = string.Format("Ip='{0}' AND OptionId={1} AND DateDiff(d,voteTime,getDate())<1", Ip, QId); if (bvIp.Exists(strWhere)) { context.Response.Write("001");//同一個IP一天只能對某一個問題投一次票 } else { int optId = 0; string[] arry = null; if (optionId.IndexOf(',') >= 0) { optionId = optionId.TrimEnd(','); if (optionId.IndexOf(',') >= 0)//多項選擇 { arry = optionId.Split(','); } else { arry = new string[1] { optionId }; } } EEY.Lib.Model.VoteIp vmodel = new EEY.Lib.Model.VoteIp(); vmodel.Ip = Ip; vmodel.OptionId = QId; vmodel.VoteTime = DateTime.Now; bvIp.Add(vmodel); if (!arry.Equals(null)) { EEY.Lib.BLL.Option bopt = new EEY.Lib.BLL.Option(); for (int i = 0; i < arry.Length; i++) { optId = StrUtil.ToInt32(arry[i], 0); bopt.UpdateCount(optId); } int total = bopt.GetQuestionVote(QId); EEY.Lib.BLL.Question bq = new EEY.Lib.BLL.Question(); if ( bq.UpdateVote(QId, total)>0) { context.Response.Write("002");//添加成功 } } } } catch (System.Exception ex) { context.Response.Write(ex.Message); } } }
通過測試發現,提交投票時候,同一個IP的確只能投一次,即查資料庫票數記錄即可以知道(第一次提交之後更新票數,但第一次提交之後票數都沒有變過)。
每一次在前台點擊投票都提示“投票成功”,實際上是沒有更新記錄。
顯然不是我們要的結果。因此可以斷定,肯定是ajax緩衝問題,存在緩衝的情況下它不會每次都執行後台代碼。從而可以斷定是前台提交的問題,及時的提交而不是返回緩衝前一次的結果。
解決辦法:
在提交時加上時間戮
即在postUrl處修改為:
var postUrl="/ashx/Vote.ashx?Id="+obj+"&optionId="+selList+"&guid="+new Date().getTime();
//+"&guid="+new Date().getTime();
加上這時間之後,問題解決。顯然ajax即時的返回幕後處理結果,我們目的達到。OK
總結
Ajax在解決緩衝時有三種辦法。
1、加時間戮
對於一個瀏覽器,你的第一次點擊是會調用rpc請求的, 但是你再用同一個瀏覽器提交表單的時候, rpc不會被提交, 因為參數一樣, 這個可能是ajax的XMLHttpRequest對象的問題, 如設定了時間間隔了,實際上是(new ActiveXObject("Microsoft.XMLHTTP"))所以, 在實際操作的時候, 給rpc的參數傳遞一個沒有用的guid= new Date().getTime()
一個時間戳記 ,以保證每次的點擊事件都會激發rpc請求, 因為這樣的參數(或者說url)是不一樣的。
為什麼要把時間戳記追加到目標url?
在某些情況下, 有些瀏覽器會把多個XMLHttpRequest請求的結果緩衝在同一個url。如果對每個請求的響應不同,這就會帶來不好的結果。把目前時間戳追加到url的最後,就能確保url的唯一性,從而避免瀏覽器的緩衝結果。
2、在要非同步擷取的頁面中寫一段禁止緩衝的代碼:
Response.Buffer =True
Response.ExpiresAbsolute =Now() - 1
Response.Expires=0
Response.CacheControl="no-cache"
3、在ajax發送請求前加上xmlHTTP.setRequestHeader("If-Modified-Since","0");可以禁止緩衝
xmlHTTP.open("get", URL, true);
xmlHTTP.onreadystatechange = callHTML;
xmlHTTP.setRequestHeader("If-Modified-Since","0");
xmlHTTP.send();