<%@ 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”思路,來實現了其中的一種,也不知道有沒有問題,還請大家多多賜教。