<%@ Page Language="C#" AutoEventWireup="true" CodeFile="JqueryAjaxLongPoll.aspx.cs" Inherits="JqueryAjaxLongPoll" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>無標題頁</title> <script type="text/javascript" src="script/jquery-1.2.6.js"></script> <script type="text/javascript"> $(document).ready(function(){ $("#Button1").bind("click",{btn:$("#Button1")},function(evdata){ $.ajax({ type:"POST", url:"JqueryAjaxLongPoll.aspx", dataType:"json", timeout:10000, data:{ajax:"1",time:"10000"}, success:function(data,textStatus){ //alert("ok!"); evdata.data.btn.click(); }, complete:function(XMLHttpRequest,textStatus){ if(XMLHttpRequest.readyState=="4"){ alert(XMLHttpRequest.responseText); } }, error: function(XMLHttpRequest,textStatus,errorThrown){ //$("#ajaxMessage").text($(this).text()+" out!") alert("error:"+textStatus); if(textStatus=="timeout") evdata.data.btn.click(); } }); }); /*$("#ajaxMessage").ajaxStart(function(){ $(this).text("准備建立請求.readyState0:"); }); $("#ajaxMessage").ajaxSend(function(evt, request, settings){ $(this).text("開始請求,准備發送數據.readyState1:"+request.readyState); }); $("#ajaxMessage").ajaxComplete(function(event,request, settings){ if(request.status==200) $(this).text("請求完成.readyState4:"+request.readyState); }); $("#ajaxMessage").ajaxStop(function(){ $(this).text("請求結束."); });*/ }); </script> </head> <body> <form id="form1" runat="server"> <div> <input id="Button1" type="button" value="AjaxLongPoll" /> <label id="ajaxMessage"></label> </div> </form> </body> </html>
using System; using System.Data; using System.Configuration; using System.Collections; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; using System.Threading; public partial class JqueryAjaxLongPoll : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { if (Request.Form["ajax"] == "1") { //Response.End(); int time = Convert.ToInt32(Request.Form["time"]); DateTime date1 = DateTime.Now.AddMilliseconds((double)time); bool ready = false; while (Response.IsClientConnected) { Thread.Sleep(3000); if (DateTime.Compare(date1, DateTime.Now) < 0) { Response.End(); break; } //ready = true; if (ready) { Response.Write("SetValue('" + DateTime.Now.ToString() + "')"); //Response.Flush(); Response.End(); break; } else { } } } else { if (!Page.IsPostBack) { } } } }
對代碼的說明:利用jquery,很方便的就能實現ajax,上面設置了ajax的timeout時間,由於設置了timeout將會造成不能保持長連接,到了時間ajax自動會報“超時”的錯誤,也就是會調用error方法,此時textStatus=="timeout",timeout后重新進行ajax請求。服務器接受ajax請求的時候,會接收一個超時時間的值,超時的情況下服務器端的處理也立即停止。當客戶端成功獲取返回結果時,也會立即進行新的ajax請求,如此循環。
為什么要設置客戶端的ajax超時值呢?因為服務器為了保持請求(阻塞請求),必須有一個無限循環,循環的結束條件就是獲取到了返回結果,如果客戶端關閉了(客戶端瀏覽器的關閉不會發消息給服務器),服務器無法知道客戶端已經關了,這個請求沒必要處理下去了。最終會造成資源過度浪費,只要用一個折中的辦法,限制超時時間。
可以不必設置客戶端ajax的超時時間,但進行請求的時候傳遞一個超時值給服務器,服務器在處理的時候,如果超時時間到了的話,還沒有客戶端需要的結果,這時傳遞一個超時信息給客戶端,客戶端接收到了此信息,根據情況重新進行ajax請求。XMLHttpRequest沒有超時的參數,Jquery用window.setTimeout自己封裝的(到了定時時間運行超時處理方法,和XMLHttpRequest結束方法)。可以根據這個思路來改變一下,IBM上介紹的LONG POLL好像也是這樣的。
$(document).ready(function(){ $("#Button1").bind("click",{btn:$("#Button1")},function(evdata){ $.ajax({ type:"POST", url:"JqueryAjaxLongPoll.aspx", dataType:"json", data:{ajax:"1",time:"6000000"}, success:function(data,textStatus){ //成功 if(data.success=="1"){ //客戶端處理 //... ///重新請求 evdata.data.btn.click(); } //超時 if(data.success=="0"){ evdata.data.btn.click(); } }, complete:function(XMLHttpRequest,textStatus){ if(XMLHttpRequest.readyState=="4"){ alert(XMLHttpRequest.responseText); } }, error: function(XMLHttpRequest,textStatus,errorThrown){ //$("#ajaxMessage").text($(this).text()+" out!") // alert("error:"+textStatus); // if(textStatus=="timeout") evdata.data.btn.click(); } }); });
后台代碼變更后:
if (Request.Form["ajax"] == "1") { int time = Convert.ToInt32(Request.Form["time"]); DateTime date1 = DateTime.Now.AddMilliseconds((double)time); bool ready = false; while (Response.IsClientConnected) { Thread.Sleep(3000); if (DateTime.Compare(date1, DateTime.Now) < 0) { Response.Write("{success:'0'}"); Response.End(); break; } //此處進行請求處理,有結果了置ready = true //ready = true; if (ready) { Response.Write("{success:'1'}"); Response.End(); break; } } } else { if (!Page.IsPostBack) { } }
上面的方法應該就可以滿足要求了,具體的超時時間可以根據情況來設置。這也是我根據IBM上介紹的“server push”思路,來實現了其中的一種,也不知道有沒有問題,還請大家多多賜教。