详解Ajax技术

来源:互联网 发布:微信回调域名 编辑:程序博客网 时间:2024/05/17 01:57

http://blog.csdn.net/lovesomnus/article/details/24028229


Ajax 能够做什么?

        如今 Google Suggest 和 Google Maps 使用了 Ajax,通过 Ajax,我们可以使得客户端得到丰富的应用体验及交换操作,而用户不会感觉到有网页提交或刷新的过程,页面也不需要被重新加载,应用的数据交换都被隐藏。


       传统的 WEB 应用程序模型是这样工作的:用户的界面操作触发 HTTP 请求,服务器在接收到请求之后进行一些业务逻辑处理,如保存数据等,然后向客户端返回一个 HTML 页面。但这种方式并没有给予用户很好的应用体验,当服务器在处理数据的时候,用户则处于等待的状态,每一步操作都需要等待,太多的等待会使用户越来越没有耐心。而 Ajax 则大不相同,它通过 Ajax 引擎,使得应用过程很自然,操作很流畅,因为其只和服务器交换有用的数据,而页面显示等不必要的数据则不再重新加载。Ajax 引擎其实就是 JavaScript、XML、XMLHttpRequest 等等各项技术的综合应用。


 为什么使用AJAX?
  1、通过适当的Ajax应用达到更好的用户体验;
  2、把以前的一些服务器负担的工作转嫁到客户端,利于客户端闲置的处理能力来处理,减轻服务器和带宽的负担,从而达到节约ISP的空间及带宽租用成本的目的。

AJAX从哪里来的?
  Ajax这个概念的最早提出者Jesse James Garrett认为:
  Ajax是Asynchronous JavaScript and XML的缩写。
  Ajax并不是一门新的语言或技术,它实际上是几项技术按一定的方式组合在一在同共的协作中发挥各自的作用,它包括:
  • 使用XHTML和CSS标准化呈现;
  • 使用DOM实现动态显示和交互;
  • 使用XML和XSLT进行数据交换与处理;
  • 使用XMLHttpRequest进行异步数据读取;
  • 最后用JavaScript绑定和处理所有数据;
  Ajax的工作原理相当于在用户和服务器之间加了—个中间层,使用户操作与服务器响应异步化。并不是所有的用户请求都提交给服务器,像—些数据验证和数据处理等都交给Ajax引擎自己来做,只有确定需要从服务器读取新数据时再由Ajax引擎代为向服务器提交请求。


AJAX的核心技术有哪些?
  虽然Garrent列出了7条Ajax的构成技术,但个人认为,所谓的Ajax其核心只有JavaScript、XMLHTTPRequest和DOM,如果所用数据格式为XML的话,还可以再加上XML这一项(Ajax从服务器端返回的数据可以是XML格式,也可以是文本等其他格式)。

  在旧的交互方式中,由用户触发一个HTTP请求到服务器,服务器对其进行处理后再返回一个新的HTHL页到客户端,每当服务器处理客户端提交的请求时,客户都只能空闲等待,并且哪怕只是一次很小的交互、只需从服务器端得到很简单的一个数据,都要返回一个完整的HTML页,而用户每次都要浪费时间和带宽去重新读取整个页面。

  而使用Ajax后用户从感觉上几乎所有的操作都会很快响应没有页面重载(白屏)的等待。

XMLHttpRequest简称 XmlHttp

        它是一套可以在Javascript、VbScript、Jscript等脚本语言中通过http协议传送或从接收XML及其他数据的一套API。XmlHttp最大的用处是可以更新网页的部分内容而不需要刷新整个页面。


        来自MSDN的解释:XmlHttp提供客户端同http服务器通讯的协议。客户端可以通过XmlHttp对象(MSXML2.XMLHTTP.3.0)向http服务器发送请求并使用微软XML文档对象模型Microsoft® XML Document Object Model (DOM)处理回应。

        现在的绝对多数浏览器都增加了对XmlHttp的支持,IE中使用ActiveXObject方式创建XmlHttp对象,其他浏览器如:Firefox、Opera等通过window.XMLHttpRequest来创建xmlhttp对象。  

属性:

onreadystatechange*指定当readyState属性改变时的事件处理句柄。只写readyState返回当前请求的状态,只读.responseBody将回应信息正文以unsigned byte数组形式返回.只读responseStream以Ado Stream对象的形式返回响应信息。只读responseText将响应信息作为字符串返回.只读responseXML将响应信息格式化为Xml Document对象并返回,只读status返回当前请求的http状态码.只读statusText返回当前请求的响应行状态,只读
着重介绍下readyState属性

返回XMLHTTP请求的当前状态,每个数值代表一个状态
0 (未初始化)对象已建立,但是尚未初始化(尚未调用open方法)1 (初始化)对象已建立,尚未调用send方法2 (发送数据)send方法已调用,但是当前的状态及http头未知3 (数据传送中)已接收部分数据,因为响应及http头不全,这时通过responseBody和responseText获取部分数据会出现错误,4 (完成)数据接收完毕,此时可以通过通过responseBody和responseText获取完整的回应数据


方法:

abort取消当前请求getAllResponseHeaders获取响应的所有http头getResponseHeader从响应信息中获取指定的http头open创建一个新的http请求,并指定此请求的方法、URL以及验证信息(用户名/密码)send发送请求到http服务器并接收回应setRequestHeader单独指定请求的某个http头

如何正确使用Ajax?

这里我们拿一个项目中常用的用户注册校验是否有重复用户名存在的案例来演示。并分别用get方式回传json,post方式回传json,post方式回传xml来演示。

首先我们得考虑在不同浏览器下如何获得XmlHttp对象
[javascript] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. function creatXmlHttpRequest()   
  2. {  
  3.     if (typeof XMLHttpRequest != 'undefined')  
  4.     {  
  5.         return new XMLHttpRequest();  
  6.     }  
  7.     else if (typeof ActiveXObject != 'undefined')  
  8.     {  
  9.         var MSXML = ['MSXML2.XMLHTTP.6.0''MSXML2.XMLHTTP.5.0',  
  10.                 'MSXML2.XMLHTTP.4.0''MSXML2.XMLHTTP.3.0''MSXML2.XMLHTTP',  
  11.                 'Microsoft.XMLHTTP'];  
  12.         for (var i = 0; MSXML.length; i ++)  
  13.         {  
  14.             try{  
  15.                 return new ActiveXObject(version[i]);  
  16.             }catch (e)  
  17.             {  
  18.                 //.......  
  19.             }  
  20.         }  
  21.     }  
  22.     else  
  23.     {  
  24.         throw new Error('您的系统或浏览器不支持XHR对象!');  
  25.     }  
  26. }  

GET方式回传json
[javascript] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. function checkUserByAjaxGet()   
  2. {  
  3.     // 第一步,得到一个XMLHttpRequest对象  
  4.     // var xhr=new XMLHttpRequest();  
  5.     // 如果说IE6,就需要使用Active组建  
  6.     // xmlhttp=new ActiveXObject(MSXML[n]);  
  7.     var xhr = creatXmlHttpRequest();  
  8.     var name = document.rgform.username.value;  
  9.     // 设置一个事件的监听函数  
  10.     xhr.onreadystatechange = function()   
  11.     {  
  12.         if (xhr.readyState == 4)   
  13.         {  
  14.             if (xhr.status == 200 || xhr.status == 304)   
  15.             {  
  16.                 var ret = xhr.responseText;  
  17.                 var _ret = eval('(' + ret + ')');   
  18. //              var _ret = JSON.parse(ret);  
  19.                 document.getElementById("msg").innerHTML = _ret.tip;  
  20.                 if (_ret.success = true)   
  21.                 {  
  22.                     document.rgform.username.focus();  
  23.                 }  
  24.             }  
  25.         }  
  26.     }  
  27.     // 第二步,准备一个连接请求  
  28.     xhr.open("get""checkuserByJSON.jsp?name=" + name, true);  
  29.     // 第三步,发起请求  
  30.     xhr.send(null);  
  31. }  

POST方式回传json
[javascript] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. function checkUserByAjaxPost()   
  2. {  
  3.     // 第一步,创建xhr对象  
  4.     var xhr = creatXmlHttpRequest();  
  5.     var name = document.rgform.username.value;  
  6.     // 第二步,设置一个事件的监听函数  
  7.     xhr.onreadystatechange = function()   
  8.     {  
  9.         if (xhr.readyState == 4)   
  10.         {  
  11.             if (xhr.status == 200 || xhr.status == 304)   
  12.             {  
  13.                 var ret = xhr.responseText;  
  14.                 var _ret = eval('(' + ret + ')');   
  15. //              var _ret = JSON.parse(ret);  
  16.                 document.getElementById("msg").innerHTML = _ret.tip;  
  17.                 if (_ret.success = true)   
  18.                 {  
  19.                     document.rgform.username.focus();  
  20.                     alert(xhr.getResponseHeader("Content-Length"));  
  21.                     alert(xhr.getResponseHeader("Content-Type"));  
  22.                     alert(xhr.getResponseHeader("Date"));  
  23.                     alert(xhr.getResponseHeader("Server"));  
  24.                 }  
  25.             }  
  26.         }  
  27.     }  
  28.     // 第三步,准备一个POST连接请求  
  29.     xhr.open("post""checkuserByJSON.jsp"true);  
  30.     // 使用post方式提交,必须要加上如下一行  
  31.     xhr.setRequestHeader("Content-Type""application/x-www-form-urlencoded");  
  32.     // 第四步,发起请求  
  33.     xhr.send("name=" + name + "&password=ppppp");  
  34. }  

POST方式回传xml
[javascript] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. function checkUserByAjaxPostXml() {  
  2.     // 第一步,创建xhr对象  
  3.     var xhr = creatXmlHttpRequest();  
  4.     var name = document.rgform.username.value;  
  5.     // 第二步,设置一个事件的监听函数  
  6.     xhr.onreadystatechange = function()   
  7.     {  
  8.         if (xhr.readyState == 4)   
  9.         {  
  10.             if (xhr.status == 200 || xhr.status == 304)   
  11.             {  
  12.                 var ret = xhr.responseXML;  
  13.                 var successNode = ret.getElementsByTagName("success")[0];  
  14.                 var tipNode = ret.getElementsByTagName("tip")[0];  
  15.                 document.getElementById("msg").innerHTML = tipNode.firstChild.nodeValue;  
  16.                 if (successNode.firstChild.nodeValue == true)   
  17.                 {  
  18.                     document.rgform.username.focus();  
  19.                 }  
  20.             }  
  21.         }  
  22.     }  
  23.     // 第三步,准备一个POST连接请求  
  24.     xhr.open("post""checkuserByXML.jsp"true);  
  25.     xhr.setRequestHeader("Content-Type""application/x-www-form-urlencoded");  
  26.     // 第四步,发起请求  
  27.     xhr.send("name=" + name + "&password=ppppp");  
  28. }  

返回的的json
[html] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. <%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>  
  2. <%@ page import="java.util.*" %>  
  3. <%  
  4. String username = request.getParameter("username");  
  5. response.setContentType("application/json;charset=UTF-8");  
  6. response.setHeader("pragma","no-cache");  
  7. response.setHeader("cache-control","no-cache");  
  8. if("admin".equals(username))  
  9. {  
  10.     response.getWriter().write("{\"success\":"+true+",\"tip\":\"用户名已存在\"}");  
  11. }  
  12. else  
  13. {  
  14.     response.getWriter().write("{\"success\":"+false+",\"tip\":\"用户名可以使用\"}");  
  15. }  
  16. %>  

返回的xml
[html] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. <%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>  
  2. <%@ page import="java.util.*" %>  
  3. <%  
  4. String userId = request.getParameter("name");  
  5. response.setContentType("application/xml;charset=UTF-8");  
  6. response.setHeader("pragma","no-cache");  
  7. response.setHeader("cache-control","no-cache");  
  8. if("admin".equals(userId))  
  9. {  
  10.     response.getWriter().write("<root><success>true</success><tip>用户名已存在</tip></root>");  
  11. }  
  12. else  
  13. {  
  14.     response.getWriter().write("<root><success>false</success><tip>用户名可以使用</tip></root>");  
  15. }  
  16. %>  

界面
[html] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">  
  2. <html>  
  3.   <head>  
  4.     <title>register.html</title>  
  5.     <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">  
  6.     <meta http-equiv="description" content="this is my page">  
  7.     <meta http-equiv="content-type" content="text/html; charset=UTF-8">  
  8.       
  9.     <script type="text/javascript" src="js/register.js"></script>  
  10.     <script type="text/javascript" src="js/jquery-1.5.2.js"></script>  
  11.     <style type="text/css">  
  12.         #round {  
  13.             padding:10px; width:300px; height:150px;  
  14.             border:1px solid #000;  
  15.             -moz-border-radius: 10px;  
  16.             -webkit-border-radius: 10px;  
  17.             border-radius:10px;  
  18.             margin:10px auto;  
  19.         }  
  20.         #round div.user, #round div.pass {  
  21.             font-size:14px;  
  22.             color:#666;  
  23.             padding:15px 0;  
  24.             text-align:center;  
  25.             position: relative;  
  26.         }  
  27.         #round span{  
  28.             position: absolute;  
  29.             color:red;  
  30.             top:35px;  
  31.             left:100px;  
  32.         }  
  33.         #round input.text {  
  34.             width:200px;  
  35.             height:25px;  
  36.             border:1px solid #ccc;  
  37.             background:#fff;  
  38.             font-size:14px;  
  39.         }  
  40.         #round .button {  
  41.             padding:5px 0;  
  42.             text-align:center;  
  43.         }  
  44.     </style>  
  45.   </head>  
  46.     
  47.   <body>  
  48.     <div id="round">  
  49.         <form name="rgform" method="post" action="" >  
  50.             <div class="user">  
  51.                  用户名:<input type="text" name="username"  id="username" onchange="事件调用的方法">  
  52.                  <span id="msg"></span>  
  53.              </div>  
  54.              <div class="pass">  
  55.                 密  码:<input type="password"  name="password" id="password">  
  56.              </div>  
  57.              <div class="button"><input type="button" value="提交"/></div>  
  58.         </form>  
  59.     </div>  
  60.   </body>  
  61. </html>  

效果图

        使用过jQuery异步请求的方法的同学,肯定觉得那个相当好用,相比而言,上面写的相当繁琐,get方式和post方式请求甚至还有部分代码是有很大区别的,那应如何通过代码的方式屏蔽这些区别呢,这里我们仿一下jQuery 的$.ajax() 方法。
[javascript] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. //封装ajax  
  2. function ajax(obj) {  
  3.     var xhr = creatXmlHttpRequest();  
  4.     obj.url = obj.url + '?rand=' + Math.random();  
  5.     obj.data = params(obj.data);  
  6.     if (obj.method === 'get') obj.url += obj.url.indexOf('?') == -1 ? '?' + obj.data : '&' + obj.data;  
  7.     if (obj.async === true) {  
  8.         xhr.onreadystatechange = function () {  
  9.             if (xhr.readyState == 4) {  
  10.                 callback();  
  11.             }  
  12.         };  
  13.     }  
  14.     xhr.open(obj.method, obj.url, obj.async);  
  15.     if (obj.method === 'post') {  
  16.         xhr.setRequestHeader('Content-Type''application/x-www-form-urlencoded');  
  17.         xhr.send(obj.data);   
  18.     } else {  
  19.         xhr.send(null);  
  20.     }  
  21.     if (obj.async === false) {  
  22.         callback();  
  23.     }  
  24.     function callback() {  
  25.         if (xhr.status == 200) {  
  26.             obj.success(xhr.responseText);          //回调传递参数  
  27.         } else {  
  28.             alert('获取数据错误!错误代号:' + xhr.status + ',错误信息:' + xhr.statusText);  
  29.         }     
  30.     }  
  31. }  

[javascript] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. //名值对转换为字符串  
  2. function params(data) {  
  3.     var arr = [];  
  4.     for (var i in data) {  
  5.         arr.push(encodeURIComponent(i) + '=' + encodeURIComponent(data[i]));  
  6.     }  
  7.     return arr.join('&');  
  8. }  

调用我们封装的ajax方法
[javascript] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. window.onload = function(){  
  2.     document.getElementById("username").onchange = function(){  
  3.         ajax({  
  4.             method : 'post',  
  5.             url : 'checkuserByJSON.jsp',  
  6.             data : {  
  7.                 'username' : document.rgform.username.value,  
  8.                 'password' : document.rgform.password.value  
  9.             },  
  10.             success : function (text) {  
  11.                     var _ret = eval('(' + text + ')');   
  12.                     document.getElementById("msg").innerHTML = _ret.tip;  
  13.             },  
  14.             async : true  
  15.         });  
  16.     }  
  17. }  

我们给ajax传的就是一个object对象,是不是已经很贴近jQuery的方式了呢。

0 0