All articles| All Pictures| All Softwares| All Video| Go home page| Write articles| Upload pictures

Reading number is top 10 articles
动态sql语句基本语法_[SQL Server教程]
新标准的熟悉和入门_[Html教程]_0
如何创建SQL Server 2000故障转移群集_[SQL Server教程]
php5的simplexml解析错误_[PHP教程]
php采用数据库保存session_[PHP教程]
PHP和MySQL基础教程(二)_[PHP教程]
ASP.NET技巧:Session丢失原因与解决方案小结_.net资料_编程技术
visual c++ 常用的mfc CRuntimeClass结构
delphi类型文件声明方式
使用MD5加密注册用户密码的简单示例_.net资料_编程技术
Reading number is top 10 pictures
黑社会大哥相亲
In the world the most mysterious 21 place landscape2
Ashlynn Brooke a group sexy photo4
Beauty Sun Feifei
张家界的玻璃桥
Beautiful vacuum girl3
最2B的公司制度
Kim jong il's mistress, national beauty JinYuJi actor1
Summer is most suitable for young people to travel in China7
photos of ashlynn brooke(ashlynn brooke的美图)
Download software ranking
变速齿轮3.26
少妇苏霞全本
Unix video tutorial18
Kung.Fu.Panda.2
Visual C++界面编程技术
电脑知识及技巧大合集
SP3 for SQL2000
传奇私服架设教程
Tram sex maniac 2 (H) rar bag15
Twenty piece of palm leaf
归海一刀 published in(发表于) 2014/1/30 0:51:45 Edit(编辑)
Asp.Net,Ajax,学习笔记14,扩展Microsoft,AJAX,Library的异步通信层_[Asp.Net教程]

Asp.Net,Ajax,学习笔记14,扩展Microsoft,AJAX,Library的异步通信层_[Asp.Net教程]

Asp.Net Ajax 学习笔记14 扩展Microsoft AJAX Library的异步通信层_[Asp.Net教程]























这一讲的内容主要是详细的了解Asp.Net Ajax异步通信层的实现方式。课程首先说明了各个类的作用




WebRequest类:收集(存储)请求信息
WebRequestExecutor类:发送请求、反馈服务器端回复的结果
XMLHttpExecutor:封装了XMLHttpRequest的Executor
WebRequestManager类:用于管理异步通讯层与服务器端的通信
然后说明了一下异步通信层组件协作过程




异步通信层组件协作过程
WebRequestManager确定Executor
触发WRM的invokingRequest事件
执行Executor的executeRequest方法
2. Executor返回、超时或被取消




执行WebRequest的completed方法
触发WRM的completedRequest事件
触发WebRequest的complete事件
下面是使用Asp.Net Ajax类库的详细调用代码,我会将注释标明。







我们着重关注WebRequest的invoke调用




function SysNetWebRequestinvoke()
{
//检查调用时是否存在参数,存在就抛出异常
if (arguments.length !== 0) throw Error.parameterCount();
//检查这个WebRequest是否已经被调用了,已经被调用了就抛出异常
if (this._invokeCalled)
{
throw Error.invalidOperation(Sys.Res.invokeCalledTwice);
}




//使用WebRequestManager这个静态实例的方法executeRequest(执行请求),把当前执行invoke
//的对象作为参数,为什么说WebRequestManager是一个静态实例,因为在注册
//WebRequestManager类之后,有这样一段代码Sys.Net.WebRequestManager = new Sys.Net._WebRequestManager(),
//这说明Sys.Net命名空间里存在一个_WebRequestManager类型,在这个命名空间里有一个叫WebRequestManager实例,他的类型就是_WebRequestManager
Sys.Net.WebRequestManager.executeRequest(this);
//将已经调用标志设置为true
this._invokeCalled = true;
}




上面这段代码,我们着重关注WebRequestManager的executeRequest(WebRequest request)方法




function SysNet_WebRequestManagerexecuteRequest(webRequest)
{
//校验参数是否时WebRequest类型
var e = Function._validateParams(arguments, [{name: "webRequest", type: Sys.Net.WebRequest}]);
if (e) throw e;




//得到webRequest的执行者对象
var executor = webRequest.get_executor();
//如果存在执行者,我们在客户端调用没有设置webRequest的执行者
//运行到这里应该进入这个if判断
if (!executor)
{
//如果WebRequest对象不存在执行者
var failed = false;
try
{
//得到WebRequestManger对象的默认执行者类型
var executorType = eval(this._defaultExecutorType);
//生成这个执行者对象,这个对象实际上就是XmlHttpExecutor
//XmlHttpExecutor实际上是继承与WebRequestExecutor类
executor = new executorType();
}
catch (e)
{
failed = true;
}




//如果执行失败,或者执行者没有继承WebRequestExecutor类,就是说不是WebRequestExecutor实例
//或者executor为空,那么抛出异常
if (failed || !Sys.Net.WebRequestExecutor.isInstanceOfType(executor) || !executor)
{
throw Error.argument("defaultExecutorType", String.format(Sys.Res.invalidExecutorType, this._defaultExecutorType));
}




//设置WebRequest的执行者
webRequest.set_executor(executor);
}




//如果执行者取消了请求,那么就直接返回
if (executor.get_aborted())
{
return;
}




//生成一个NetworkReuqestEventArgs参数对象,用webRequest最为参数
var evArgs = new Sys.Net.NetworkRequestEventArgs(webRequest);




//得到invokingRequest事件的事件委托
var handler = this._get_eventHandlerList().getHandler("invokingRequest");
//如果存在这个事件委托,那么就调用这个事件委托
if (handler)
{
handler(this, evArgs);
}




//如果外部事件委托执行没有取消执行
if (!evArgs.get_cancel())
{
//调用执行者executor的executeRequest()(执行请求方法)
executor.executeRequest();
}
}





下面关注XmlHttpExecutor的executeRequest()方法




function SysNetXMLHttpExecutorexecuteRequest()
{
//检测参数个数,如果不等于0,那么抛出异常
if (arguments.length !== 0) throw Error.parameterCount();




//得到WebRequest对象,用来将保存的信息传递出去
//在WebRequest对象的set_executor方法里,已经将执行者对应的
//WebRequest对象设置到执行者中,并且set_executor方法是基类
//WebRequestExecutor类的方法,这里调用的是基类的方法
this._webRequest = this.get_webRequest();




//判断这个执行者是否已经开始传递数据,如果已经开始传递,那么抛出异常
if (this._started)
{
throw Error.invalidOperation(String.format(Sys.Res.cannotCallOnceStarted, 'executeRequest'));
}




//判断webRequest对象是否为空,为空就抛出异常
if (this._webRequest === null)
{
throw Error.invalidOperation(Sys.Res.nullWebRequest);
}




//得到WebReuqest对象的body
var body = this._webRequest.get_body();
//得到WebReuqest对象的header集合
var headers = this._webRequest.get_headers();
//这一段代码是标准的ajax应用
//实例化一个xmlHttpRequest对象
this._xmlHttpRequest = new XMLHttpRequest();




//给定状态改变的回调函数
this._xmlHttpRequest.onreadystatechange = this._onReadyStateChange;
//得到WebReuqest对象的请求动作
var verb = this._webRequest.get_httpVerb();
//指定请求的连接和动作,并表明是一个异步传输
this._xmlHttpRequest.open(verb, this._webRequest.getResolvedUrl(), true );




if (headers)
{
//遍历header集合
for (var header in headers)
{
var val = headers[header];
//如果header不是js函数
if (typeof(val) !== "function")
//将header设置到xmlHttpRequest对象的请求头里
this._xmlHttpRequest.setRequestHeader(header, val);
}
}




//判断动作是否是post
if (verb.toLowerCase() === "post")
{
//通过设定的头,来设置传送内容的类型
if ((headers === null) || !headers['Content-Type'])
{
this._xmlHttpRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
}




if (!body)
{
body = "";
}
}




//得到WebReuqest对象的超时时间
var timeout = this._webRequest.get_timeout();




//如果设置了超时时间
if (timeout > 0)
{
//创建一个onTimeout函数的委托,并把XmlHttpExecutor对象作为this的上下文,
//并指定在超时时间后执行这个委托,将返回的对象放在_time内部成员里方便clearTimeout
this._timer = window.setTimeout(Function.createDelegate(this, this._onTimeout), timeout);
}




this._xmlHttpRequest.send(body);




//设置执行这已经开始标识
this._started = true;
}








在上面这个方法里,我们要关注3个方法




第一个是_onReadyStateChange方法,这个方法将在ReadyState改变是被调用




this._onReadyStateChange = function ()
{
//如果readState状态为4,表明成功返回
if (_this._xmlHttpRequest.readyState === 4 )
{
//清除超时时间
_this._clearTimer();
//设置响应状态为可用
_this._responseAvailable = true;
//告诉webRequest对象,我已经完成请求了
_this._webRequest.completed(Sys.EventArgs.Empty);




//如果ajax异步传输对象不为空
if (_this._xmlHttpRequest != null)
{
//清除xmlHttpRequest的onreadystatechange委托
_this._xmlHttpRequest.onreadystatechange = Function.emptyMethod;
//清除ajax异步传输对象
_this._xmlHttpRequest = null;
}
}
}








第二个方法是_onTimeout,超时后执行的方法




this._onTimeout = function this_onTimeout()
{
if (!_this._responseAvailable)
{
//清除超时时间设置的委托
_this._clearTimer();
//设置超时标志为true
_this._timedOut = true;
//清除xmlHttpRequest异步操作对象的onreadystatechange的回调函数
_this._xmlHttpRequest.onreadystatechange = Function.emptyMethod;
//取消xmlHttpRequest对象异步传输
_this._xmlHttpRequest.abort();
//告诉webRequest对象我已经完成操作
_this._webRequest.completed(Sys.EventArgs.Empty);
_this._xmlHttpRequest = null;
}
}








第三个是XMLHttpRequest的构造函数




if (!window.XMLHttpRequest)
{
window.XMLHttpRequest = function windowXMLHttpRequest()
{
var progIDs = [ 'Msxml2.XMLHTTP', 'Microsoft.XMLHTTP' ];




for (var i = 0; i < progIDs.length; i++)
{
try
{
var xmlHttp = new ActiveXObject(progIDs[i]);
return xmlHttp;
}
catch (ex)
{
}
}




return null;
}
}








这是为了适应各种类型的浏览器,与我们原来创建标准的ajax异步传输例子相同




我们还要关注WebRequest.completed方法




function SysNetWebRequestcompleted(eventArgs)
{
//检测参数
var e = Function._validateParams(arguments, [{name: "eventArgs", type: Sys.EventArgs}]);
if (e) throw e;




//得到WebRequestManger的completedRequest事件委托
var handler = Sys.Net.WebRequestManager._get_eventHandlerList().getHandler("completedRequest");
//如果存在这样的委托,那么调用这个委托,参数为执行者和args参数
if (handler)
{
handler(this._executor, eventArgs);
}




//继续得WebRequest的completed事件委托,那么我们可以看到WebRequestManager的completedRequest事件是
//优先于WebRequest的completed事件的
handler = this._get_eventHandlerList().getHandler("completed");
//执行委托
if (handler)
{
handler(this._executor, eventArgs);
}
}








XmlHttpExecutor.abort()方法




function SysNetXMLHttpExecutorabort()
{
//判断参数
if (arguments.length !== 0) throw Error.parameterCount();




//如果执行者没有执行,抛出异常
if (!this._started)
{
throw Error.invalidOperation(Sys.Res.cannotAbortBeforeStart);
}




//如果执行者的状态已经是abort,或者相应是无效的或者超时,那么直接返回
if (this._aborted || this._responseAvailable || this._timedOut)
return;




//设置abort标志
this._aborted = true;




//清除超时设置
this._clearTimer();




//如果异步传输对象存在,并且还没有返回任何信息
if (this._xmlHttpRequest && !this._responseAvailable)
{
this._xmlHttpRequest.onreadystatechange = Function.emptyMethod;
this._xmlHttpRequest.abort();




this._xmlHttpRequest = null;
//得到WebRequest对象的Completed事件委托
var handler = this._webRequest._get_eventHandlerList().getHandler("completed");




if (handler)
{
handler(this, Sys.EventArgs.Empty);
}
}
}








我们可以看到除了超时,成功响应,错误,中断都会触发WebRequest的compeleted事件。




下面的一个例子是模仿XmlHttpExecutor类,并且支持跨域名访问




首先是ScriptReferenceExecutor类




Sys.Net.ScriptReferenceExecutor = function()
{
//初始化基类
Sys.Net.ScriptReferenceExecutor.initializeBase(this);




//设定各个字段的初始值
this._responseAvailable = false;
this._timedOut = false;
this._aborted = false;
this._started = false;
this._responseData = null;
this._statusCode = 0;
this._statusText = null;

this._uniqueKey = null;
this._timer = null;
this._scriptElement = null;




}




Sys.Net.ScriptReferenceExecutor.prototype =
{
get_responseAvailable : function()
{
return this._responseAvailable;
},

get_timedOut : function()
{
return this._timedOut;
},

get_aborted : function()
{
return this._aborted;
},

get_started : function()
{
return this._started;
},

get_responseData : function()
{
return this._responseData;
},

get_statusCode : function()
{
return this._statusCode;
},

get_statusText : function()
{
return this._statusText;
},

get_xml : function()
{
return new XMLDOM(this.get_responseData());
},

//执行请求的方法
executeRequest : function()
{
//设置开始标记为true
this._started = true;

//得到WebRequest对象,就得到了保存在WebRequest中的各种值
var request = this.get_webRequest();
//得到序列化对象
var serializer = Sys.Serialization.JavaScriptSerializer;

//得到WebRequest对象请求的url地址
var scriptUrl = request.get_url() + "?";
//组合头集合,并将头集合序列化,并且用Url转换字符
scriptUrl += (("headers=") + encodeURIComponent(serializer.serialize(request.get_headers())));
//组合body
scriptUrl += ("&body=" + encodeURIComponent(serializer.serialize(request.get_body())));

//得到一个执行者对象的唯一标识符,方便找到对应的执行者
var uniqueKey = this._uniqueKey = this._generateUniqueKey();
scriptUrl += ("&uniqueKey=" + encodeURIComponent(serializer.serialize(uniqueKey)));
//设置对应的执行者到执行者集合里
Sys.Net.ScriptReferenceExecutor._executors[uniqueKey] = this;

//创建脚本元素
var scriptElement = this._scriptElement = document.createElement("script");
scriptElement.type = "text/javascript";
scriptElement.language = "javascript";
//将脚本元素的src设置为组合好的url
scriptElement.src = scriptUrl;
//得到页面的head元素,因为head没有ID,只能通过TagName得到,然后将
//脚本元素追加到头
document.getElementsByTagName("head")[0].appendChild(scriptElement);

//得到超时事件
var timeout = request.get_timeout();
if (timeout > 0)
{
//设置超时后执行的委托
this._timer = window.setTimeout(
Function.createDelegate(this, this._onTimeout), timeout);
}

},

_onTimeout : function()
{
this.complete(null, null, null, false, true, false);
},

abort : function()
{
this.complete(null, null, null, false, false, true);
},

_generateUniqueKey : function()
{
return Math.random().toString();
},

//执行者的完成函数参数为状态代码、状态描述、body、是否返回成功、是否超时、是否中断操作
complete : function(statusCode, statusText, body, responseAvailable, timedOut, aborted)
{
this._statusCode = statusCode;
this._statusText = statusText;
this._responseData = body;
this._responseAvailable = responseAvailable;
this._timedOut = timedOut;
this._aborted = aborted;

//清除超时事件
if (this._timer)
{
window.clearTimeout(this._timer);
}
//移除已经提交给服务气的脚本元素,也就是url
document.getElementsByTagName("head")[0].removeChild(this._scriptElement);
//删除已经执行的执行者
delete Sys.Net.ScriptReferenceExecutor._executors[this._uniqueKey];

//调用WebRequest的completed方法
this.get_webRequest().completed(Sys.EventArgs.Empty);
}
}
//注册类
Sys.Net.ScriptReferenceExecutor.registerClass("Sys.Net.ScriptReferenceExecutor", Sys.Net.WebRequestExecutor);
Sys.Net.ScriptReferenceExecutor._executors = new Object();
//执行者的静态complete方法
Sys.Net.ScriptReferenceExecutor.complete = function(uniqueKey, statusCode, statusText, body)
{
//判断执行者是否存在
var executor = Sys.Net.ScriptReferenceExecutor._executors[uniqueKey];
if (executor)
{
//调用执行者对象的complete方法。
executor.complete(statusCode, statusText, body, true, false, false);
}
}




再是接受请求的服务端




<%@ WebHandler Language="C#" Class="ScriptReferenceExecutor" %>




using System;
using System.Web;
using System.Collections.Generic;
using System.Web.Script.Serialization;




public class ScriptReferenceExecutor : IHttpHandler {

public void ProcessRequest (HttpContext context)
{
context.Response.ContentType = "text/plain";




// context.Response.Write("alert('Message Received!');");




//得到序列化对象
JavaScriptSerializer serializer = new JavaScriptSerializer();
//反序列化头集合为字典集合
Dictionary headers = serializer.Deserialize>(
context.Request.QueryString["headers"]);
//反序列化body为字符串
string body = serializer.Deserialize(context.Request.QueryString["body"]);
//反序列化执行者对象的标识
string uniqueKey = serializer.Deserialize(context.Request.QueryString["uniqueKey"]);




string action = headers["action"];
if (action == "normal")
{
this.SendResponse(context, uniqueKey, 200, "OK", "You've send: " + body);
}
else if (action == "error")
{
this.SendResponse(context, uniqueKey, 500, "Error", null);
}
else
{
System.Threading.Thread.Sleep(5000);
}
}




//发送响应信息
private void SendResponse(HttpContext context, string uniqueKey, int statusCode, string statusText, string body)
{
//调用ScriptReferenceExecutor的静态方法complete
context.Response.Write("Sys.Net.ScriptReferenceExecutor.complete('" + uniqueKey + "', ");
context.Response.Write("'" + statusCode + "', ");
context.Response.Write("'" + statusText + "', ");
context.Response.Write(new JavaScriptSerializer().Serialize(body) + ");");
}

public bool IsReusable
{
get
{
return false;
}
}




}
剩下的就是页面使用




<%@ Page Language="C#" %>












Use Async Communication Layer











onclick="sendRequest('normal');" />
onclick="sendRequest('error');" />
onclick="sendRequest('abc')" />
onclick="webRequest.get_executor().abort()" />





这就是继承并扩展WebRequestExecutor类

















































添加到del.icio.us 添加到新浪ViVi 添加到百度搜藏 添加到POCO网摘 添加到天天网摘365Key 添加到和讯网摘 添加到天极网摘 添加到黑米书签 添加到QQ书签 添加到雅虎收藏 添加到奇客发现 diigo it 添加到饭否 添加到飞豆订阅 添加到抓虾收藏 添加到鲜果订阅 digg it 貼到funP 添加到有道阅读 Live Favorites 添加到Newsvine 打印本页 用Email发送本页 在Facebook上分享


Disclaimer Privacy Policy About us Site Map

If you have any requirements, please contact webmaster。(如果有什么要求,请联系站长)
Copyright ©2011-
uuhomepage.com, Inc. All rights reserved.