感 于Ajax请求的使用为RIA(Rich Internet Applications)的开始,但大多数刚接触富客户端的同学还不是很清楚具体的使用方法,所以根据自己的使用心得写下此篇Blog留作拾遗。
(PS: 看网上大多数的技术Blog都写的毫无生气,只有严谨的态度,所以我一直在努力尝试使用生趣的方式展现技术文章,毕竟希望技术能带给大家快乐,乐知才最重要,生活才最最重要)
大概在2005年末,开始接触Ajax技术,开始于对《Ajax基础教程-Foundations of Ajax》 一书的阅读,其深入浅出的讲述方式、典型的实例和简洁清晰的代码,让这本书很适合刚开始使用Ajax技术的Web开发人员用来基础学习。
此书中的例子是最原始的Ajax使用方式,没有任何的封装及使用JS类库,也因当时的Prototype类库不是很成熟。对于这种未加封装的Ajax使用,自然就会面临Web浏览器类型的判别及数据乱码的问题,所以以这种方式写Ajax请求不免很多的判断条件的繁琐代码,让人看起来以为你是在coding凑数,无良的骗取钱财。以下是这些繁琐代码的示例,有兴趣的同学可以研究一下:
// Origin Ajax program paradigm var xmlHttp; // 判断浏览器,决定使用哪种创建请求的方式 function createXMLHttpRequest(){ if(window.ActiveXObject){ xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); } else if(window.XMLHttpRequest){ xmlHttp = new XMLHttpRequest(); } } // 回调方法中需判断浏览器的返回状态 function callBack(){ if(xmlHttp.readyState == 4){ if(xmlHttp.status == 200){ var message =xmlHttp.responseText; if(message == 'T'){ alert("Insert successful!"); opener.location.reload(); self.close(); } else if(message == 'F'){ alert("Insert failed!"); } } } } // function sendSaveURL(){ var tableId = $F("tableId"); tableId = trim(tableId); var validateValue = inputValidate( '表名:tableId:text', '机构:bankId:text', '币种:currId:text', '日期:reportDate:date', '申请理由:reason:text' ); if(validateValue){ var queryString = Form.serialize("form1"); // 需使用JS添加时间参数,确保服务器端的请求认定 var url = "saveRedoApply.do?timeStamp=" + new Date().getTime(); createXMLHttpRequest(); // 设置xmlHttp请求的报文头 xmlHttp.open("POST",url,false); xmlHttp.onreadystatechange = callBack; xmlHttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded;charset=utf-8"); xmlHttp.send(queryString); return xmlHttp.responsText; } }
上面代码中的方法已做了注释,从中可以看出未加任何封装的Ajax请求的繁琐。后来自己封装了以上方法才看起来简洁些。
根据定义,Ajax请求的生命周期为:
这也是开发前必须清楚的事项。
随后Prototype中也提供了比较稳定易用的Ajax封装,这使得使用Ajax请求不必再了解Origin般原汁原味的繁琐处理了。
下面是Prototype的Ajax实例:
new Ajax.Request('/your/url', { onSuccess: function(transport) { // yada yada yada } });
可以看出来封装后的确很易用,概念也明朗了许多。
然后是ExtJS中的Ajax对象提供的请求方法,很类似于Prototype的封装及使用方式。就Get及Post两种方式说明一下
其使用方式,首先来看Get方式:
Ext.Ajax.request({ url: 'dashboardChartFormProvider.do', success: function(response) { // 接收响应文本的示例 var str = response.responseText; // 将响应转换为对象的示例 var obj = response.responseText.evalJSON(); }, failure: Ext.emptyFn, params: { pid: parmId } });
Ext的ajax默认的请求方式为Get,所以也就不用特别声明使用何种请求方式了。url 是请求的链接,success 是请求成功后的回调方法,failure 是失败后的回调方法,params 为请求参数。
在这里特别要说明的是对于success和failure方法的理解,对此有很多小盆友有误解,认为后台成功后设置响应参数success为true自然就调用成功的处理方法,否则则调用十倍的处理方法,但发现不管后台(backend)处理逻辑失败与否最后调用的都是Ajax的success方法,而不解。其实这里的ajax的success方法指的并不是逻辑上的成功或失败,而指的是http通讯的响应状态成功与否,也就是在上面origin那段代码示例中判断的xmlHttp.status == 200的响应状态。这样我们也就明确了回调方法的使用,对于逻辑上的成功失败的判断需要我们自己在success中完成并添加对应的处理方法。
另附xmlHttp.statu状态码,具体如下:
100:Continue 101:Switching Protocols 102:Processing 200:OK 201:Created 202:Accepted 203:Non-Authoriative Information 204:No Content 205:Reset Content 206:Partial Content 207:Multi-Status 300:Multiple Choices 301:Moved Permanently 302:Found 303:See Other 304:Not Modified 305:Use Proxy 306:(Unused) 307:Temporary Redirect 400:Bad Request 401:Unauthorized 402:Payment Granted 403:Forbidden 404:File Not Found 405:Method Not Allowed 406:Not Acceptable 407:Proxy Authentication Required 408:Request Time-out 409:Conflict 410:Gone 411:Length Required 412:Precondition Failed 413:Request Entity Too Large 414:Request-URI Too Large 415:Unsupported Media Type 416:Requested range not satisfiable 417:Expectation Failed 422:Unprocessable Entity 423:Locked 424:Failed Dependency 500:Internal Server Error 501:Not Implemented 502:Bad Gateway 503:Service Unavailable 504:Gateway Timeout 505:HTTP Version Not Supported 507:Insufficient Storage
最后让我们看看Post方式的请求方法,Post可以使用url或form的方式来发送请求。首先是form的方式,示例代码如下:
Ext.Ajax.request({ form: 'formId', method: 'POST', success: function(response, opt) { // TODO: finish this method }, failure: Ext.emptyFn });
<!-- 表单示例 --> <form id='foo' method='post' action='something.do'> <input name='parm1' type="text" /> <input name='parm2' type="text" /> <input name='parm3' type="text" /> </form>
方法很简洁,不过不足之处是需要由你来维护表单中的值,而且html也中的代码也会因为form而增多。而使用url的方式就会利用js的对象技术而使html页更简洁些,示例如下:
Ext.Ajax.request({ url: 'something.do', method: 'POST', params: form, success: function(response) { // TODO: finshed this method here }, failure: Ext.emptyFn });
/** * Object for ajax request defined */ function Object1(){ this.parm1 = ""; this.parm2 = ""; this.parm3 = ""; } ChartForm.prototype.getParm1 = function(){ return this.parm1; } ChartForm.prototype.setParm1 = function(parm1){ this.parm1= parm1; }
其中params中对应填入你的js请求的Object,此种方式优点在于利用JS的面向对象的封装方式来做ajax请求,代码更为简洁,设计思路更为清晰。而这样前台为JS对象,返回后将其映射为java对象的做法让你可以利用OO的思想来开发Web程序,这也是目前JS编程的流行的做法,你可以更多的关注领域模型的设计,对于你来说前后台交互所面对的都是业务对象。
至此,我已简要的向你介绍了Ajax的请求使用历程。通过此篇你可以学习到ajax的原始请求形式,利用类库简化后的请求,及如何使用JS面向对象的方式来与后台交互,还有Ajax的生命周期及状态码的意义。值得注意的是ext对于ajax封装后的success方法的理解,这里的成功指的是http通讯状态的成功而非方法逻辑上的成功与否。
让我们继续关注Ajax能带给我们什么惊喜。