DWREngine._sendData 描述了dwr框架如何发送请求,它的调用栈如下:
(--〉DWREngine._execute--〉DWREngine.endBatch--〉DWREngine._sendData)
/**
* @private Actually send the block of data in the batch object.
*/
DWREngine._sendData = function(batch) {
// If the batch is empty, don't send anything
//通常此时batch.map.callCount为1,在DWREngine._execute被++过了
if (batch.map.callCount == 0) return;
// Call any pre-hooks
//如果有任何preHooks,那么进入下面的if块,通常没有
for (var i = 0; i < batch.preHooks.length; i++) {
batch.preHooks[i]();
}
//调用preHooks的函数组后,清空preHooks
batch.preHooks = null;
// Set a timeout
//如果存在timeout且不为0,那么进入下面的if块,通常情况下不存在
if (batch.timeout && batch.timeout != 0) {
batch.interval = setInterval(function() {
clearInterval(batch.interval);
DWREngine._abortRequest(batch);
}, batch.timeout);
}
// A quick string to help people that use web log analysers
//定义一个临时变量存储服务器端的特定路径
var statsInfo;
if (batch.map.callCount == 1) {
statsInfo = batch.map["c0-scriptName"] + "." + batch.map["c0-methodName"] + ".dwr";
}
//通常情况下,不会进入下面的else块
else {
statsInfo = "Multiple." + batch.map.callCount + ".dwr";
}
// Get setup for XMLHttpRequest if possible
//设置发送请求的发送请求的客户端,不同浏览器有所不同
if (batch.method == DWREngine.XMLHttpRequest) {
if (window.XMLHttpRequest) {
batch.req = new XMLHttpRequest();
}
// IE5 for the mac claims to support window.ActiveXObject, but throws an error when it's used
else if (window.ActiveXObject && !(navigator.userAgent.indexOf('Mac') >= 0 && navigator.userAgent.indexOf("MSIE") >= 0)) {
batch.req = DWREngine._newActiveXObject(DWREngine._XMLHTTP);
}
}
//定义临时变量存储请求字符串
var query = "";
//定义临时变量存储batch.map的各个属性
var prop;
//如果请求客户端存在,通常是存在的,至少在IE和firefox中是存在的
if (batch.req) {
//设置batch.map.xml
batch.map.xml = "true";
// Proceed using XMLHttpRequest
//如果请求是异步的,通常如此
if (batch.async) {
//设置回调函数即DWREngine._stateChange
batch.req.onreadystatechange = function() {
DWREngine._stateChange(batch);
};
}
// Workaround for Safari 1.x POST bug
//以下代码用于适应Safari浏览器,如果不使用无需关心
var indexSafari = navigator.userAgent.indexOf('Safari/');
if (indexSafari >= 0) {
// So this is Safari, are we on 1.x? POST is broken
var version = navigator.userAgent.substring(indexSafari + 7);
var verNum = parseInt(version, 10);
if (verNum < 400) {
batch.verb == "GET";
}
// else if (verNum <= 417) {
// batch.map.isBrokenSafari2 = "true";
// }
}
//如果以GET方式请求,进入下面的代码段,通常是POST(dwr默认),所以无需关心下面的if块
if (batch.verb == "GET") {
// Some browsers (Opera/Safari2) seem to fail to convert the value
// of batch.map.callCount to a string in the loop below so we do it
// manually here.
batch.map.callCount = "" + batch.map.callCount;
for (prop in batch.map) {
var qkey = encodeURIComponent(prop);
var qval = encodeURIComponent(batch.map[prop]);
if (qval == "") {
if (DWREngine._warningHandler) {
DWREngine._warningHandler("Found empty qval for qkey=" + qkey);
}
}
query += qkey + "=" + qval + "&";
}
query = query.substring(0, query.length - 1);
try {
batch.req.open("GET", batch.path + "/exec/" + statsInfo + "?" + query, batch.async);
batch.req.send(null);
if (!batch.async) {
DWREngine._stateChange(batch);
}
}
catch (ex) {
DWREngine._handleMetaDataError(null, ex);
}
}
//默认情况下进入下面的else块
else {
//遍历batch.map,将其属性放入请求字符串中
for (prop in batch.map) {
if (typeof batch.map[prop] != "function") {
query += prop + "=" + batch.map[prop] + "\n";
}
}
//发送请求开始
try {
// This might include Safari too, but it shouldn't do any harm
// if (navigator.userAgent.indexOf('Gecko') >= 0) {
//
batch.req.setRequestHeader('Connection', 'close');
// }
//打开连接
batch.req.open("POST", batch.path + "/exec/" + statsInfo, batch.async);
//设置头
batch.req.setRequestHeader('Content-Type', 'text/plain');
//发送
batch.req.send(query);
//如果不是异步那么进入下面的块(即手动调用钩子而不是通过xmlhttprequest的属性)通常是异步所以无需关心下面的代码
if (!batch.async) {
DWREngine._stateChange(batch);
}
}
catch (ex) {
DWREngine._handleMetaDataError(null, ex);
}
}
}
//如果请求的客户端不存在,那么进入下面的else块,通常情况下是存在,所以无需关心下面的代码
else {
batch.map.xml = "false";
var idname = "dwr-if-" + batch.map["c0-id"];
// Proceed using iframe
batch.div = document.createElement('div');
batch.div.innerHTML = "<iframe src='javascript:void(0)' frameborder='0' width='0' height='0' id='" + idname + "' name='" + idname + "'></iframe>";
document.body.appendChild(batch.div);
batch.iframe = document.getElementById(idname);
batch.iframe.setAttribute('style', 'width:0px; height:0px; border:0px;');
if (batch.verb == "GET") {
for (prop in batch.map) {
if (typeof batch.map[prop] != "function") {
query += encodeURIComponent(prop) + "=" + encodeURIComponent(batch.map[prop]) + "&";
}
}
query = query.substring(0, query.length - 1);
batch.iframe.setAttribute('src', batch.path + "/exec/" + statsInfo + "?" + query);
document.body.appendChild(batch.iframe);
}
else {
batch.form = document.createElement('form');
batch.form.setAttribute('id', 'dwr-form');
batch.form.setAttribute('action', batch.path + "/exec" + statsInfo);
batch.form.setAttribute('target', idname);
batch.form.target = idname;
batch.form.setAttribute('method', 'post');
for (prop in batch.map) {
var formInput = document.createElement('input');
formInput.setAttribute('type', 'hidden');
formInput.setAttribute('name', prop);
formInput.setAttribute('value', batch.map[prop]);
batch.form.appendChild(formInput);
}
document.body.appendChild(batch.form);
batch.form.submit();
}
}
};
总结:
DWREngine._sendData封装了ajax发送请求的细节,
特别应该注意
1)它向谁发送请求
batch.req.open("POST", batch.path + "/exec/" + statsInfo, batch.async);
从一个例子看看请求地址(batch.path + "/exec/" + statsInfo)到底是什么
请求地址如下(来自一个真实的例子)
/dwr/exec/CommentService.writeComment.dwr
2)那么除了请求地址外还附带了什么参数呢?
看看batch.req.send(query);
query为如下内容(来自一个真实的例子)
"callCount=1\n
c0-scriptName=CommentService\n
c0-methodName=writeComment\n
c0-id=6906_1152167155406\n
c0-e1=string:\n
c0-e2=string:%E5%85%AC%E5%85%B3%E5%B9%BF%E5%91%8A\n
c0-e3=string:127.0.0.1\n
c0-e4=string:0\n
c0-e6=string:1\n
c0-e7=string:9549815571\n
c0-e8=string:alex\n
c0-e5=Object:{tvUserId:reference:c0-e6,userNo:reference:c0-e7,loginName:reference:c0-e8}\n
c0-e10=string:51764\n
c0-e11=string:HIDBXMOO\n
c0-e9=Object:{videoId:reference:c0-e10,virtualName:reference:c0-e11}\n
c0-param0=Object:{title:reference:c0-e1,content:reference:c0-e2,ip:reference:c0-e3, parentId:reference:c0-e4, user:reference:c0-e5, video:reference:c0-e9}\n
xml=true\n"