ajax-XHR对象
Ajax,是对Asynchronous Javascript+XML的简写。Ajax技术的核心是XMLHttpRequest对象(XHR)。XHR为向服务器发送请求和解析服务器响应提供了流畅的接口。能够以异步方式从服务器取得更多信息,意味着用户单击后,可以不必刷新页面也能取得新数据。 一、XHR对象。 IE5是第一款引入XHR对象的浏览器。在IE5中,XHR对象是通过MSXML库中的一个ActiveX对象实现的。因此,在IE中可能会遇到3种不同版本的XHR对象, 即:MSXML2.XMLHttp、 MSXML2.XMLHttp.3.0、 MSXML2.XMLHttp.6.0。 要使用MSXML库中的XHR对象,需要编写一个函数。这个函数会尽力根据IE中可用的MSXML库的情况创建最新版本的XHR对象。例如: //适用于IE7之前的版本 function createXHR(){ if(typeof arguments.callee.activeXString != "string"){ var versions = ["MSXML2.XMLHttp.6.0","MSXML2.XMLHttp.3.0","MSXML2.XMLHttp"]; for(var i = 0,len = version.length; i < len; i++){ try{ var xhr = new ActiveXObject(versions[i]); arguments.callee.activeXString = versions[i]; return xhr; }catch (ex){ //code } } } return new ActiveXObject(arguments.callee.activeXString); } IE7、Firefox、Opera、Chrome和Safari都支持原生的XHR对象。在这些浏览器中创建XHR对象要像下面这样使用XMLHttpRequest构造函数。 var xhr = new XMLHttpRequest(); 但是如果要全部兼容,就可以使用以下代码: function createXHR(){ if(typeof XMLHttpRequest != "underfined"){ //检测原生XHR对象是否存在 return new XMLHttpRequest(); }else if(typeof ActiveXObject != "underfined"){ //检测ActiveX对象是否存在 if(typeof arguments.callee.activeXString != "string"){ var versions = ["MSXML2.XMLHttp.6.0","MSXML2.XMLHttp"]; for(var i = 0,len = version.length; i < len; i++){ try{ var xhr = new ActiveXObject(versions[i]); arguments.callee.activeXString = versions[i]; return xhr; }catch (ex){ //code } } } return new ActiveXObject(arguments.callee.activeXString); }else{ throw new Error("No XHR object available."); } }这个函数中新增的代码首先检测原生 XHR对象是否存在,如果存在则返回它的新实例。如果原生对象不存在,则检测Active对象。如果这两种对象都不存在,就抛出一个错误。写完这个函数,我们就可以使用下面的代码在所有浏览器中创建XHR对象了。
var xhr = new createXHR(); 二、XHR的用法: 1、调用第一个方法是open()。它接受三个参数:要发送的请求的类型("get"、“post”等)、请求的URL和表示是否异步发送请求的布尔值。如 xhr.open("get","example.php",false);2、发送特定的请求,必须像下面这样调用 send()方法。send()方法接受一个参数,即要作为请求主体发送的数据。如果不需要通过主体发送数据,则必须传入null,因为这个参数对有些浏览器来说是必需的。 xhr.send(null);3、等到服务器响应之后。响应的数据会自动填充 XHR对象的属性,相关的属性简介如下。 responseText:响应主体被返回的文本。 responseXML:如果响应的内容类型是"text/xml"或"application/xml",这个属性中将保存包含着响应数据的XML DOM文档。 status:响应的HTTP状态。 statusText:HTTP状态的说明。 为确保接收到适当的响应,应该像下面这样检查上述这两种状态代码。第一步检查status属性,以确定响应已经成功返回。一般来说,可以将HTTP状态代码为200作为成功的标志。 if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){ alert(xhr.statusText); }else{ alert("Request was unsuccessful:" + xhr.status); } 4、检测readyState属性。以上步骤是发送同步请求的方法,但多数情况下,我们还是要发送异步请求,才能让javascript继续执行而不必等待响应。此时,可以检测XHR对象的readyState属性,该属性表示请求/响应过程的当前活动阶段。这个属性可取的值如下: 0:未初始化。尚未调用open()方法 1:启动。已经调用open()方法,但尚未调用send()方法 2:发送。已经调用send()方法,但尚未接收到响应 3:接收。已经接收到部分响应数据。 4:完成。已经接收到全部响应数据,而且已经可以在客户端使用了。 只要readyState属性的值由一个值变成另一个值时,都会触发一次readyStatechange事件。可以利用这个事件来检测每次状态变化后readyState的值。通常,我们只对readyState值为4的阶段感兴趣。因为这时所有数据都已经就绪。不过,必须在调用open()之前指定onreadystatechange事件处理程序才能确保跨浏览器兼容性。 var xhr = new createXHR(); xhr.onreadystatechange = function(){ if(xhr.readyState == 4){ if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){ alert(xhr.statusText); }else{ alert("Request was unsuccessful:" + xhr.status); } } }; xhr.open("get",true); xhr.send(null);三、HTTP头部信息 每个http请求和响应都会带有相应的头部信息,其中有对开发人员有用,有的也没有什么用。 默认情况下,浏览器在发送XHR请求的同时,还会发送下列头部信息。 Accept:浏览器能够处理的内容类型。 Accept-Charset:浏览器能够显示的字符集。 Accept-Encoding:浏览器能够处理的压缩编码。 Accept-Language:浏览器当前设置的语言。 Connection:浏览器与服务器之间连接的类型。 Cookie:当前页面设置的任何Cookie。 Host:发出请求的页面所在的域。 Referer:发出请求的页面所在的域。 User-Agent:浏览器有用户代理字符串。 1、使用setRequestHeader()方法自定义的请求头部信息。这个方法接受两个参数:头部字段的名称和头部字段的值。而且必须在调用open()方法之后且调用send()方法之前调用。即: xhr.open("get","test.txt",true); xhr.setRequestHeader("MyHeader","MyValue"); xhr.send();2、调用XHR对象的 getResponseHeader()方法并传入头部字段名称,可以取得相应的响应头部信息。而调用 getAllResponseHeaders()方法则可以取得一个包含所有头部信息的长字符串。
var myHeader = xhr.getResponseHeader("MyHeader"); var allHerders = xhr.getAllResponseHeaders(); DEMO:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"/> <title>ajax demo</title> <script type="text/javascript"> //XHR对象的构造函数 function createXHR(){ if(typeof XMLHttpRequest != "underfined"){ //检测原生XHR对象是否存在 return new XMLHttpRequest(); }else if(typeof ActiveXObject != "underfined"){ //检测ActiveX对象是否存在 if(typeof arguments.callee.activeXString != "string"){ var versions = ["MSXML2.XMLHttp.6.0",len = version.length; i < len; i++){ try{ var xhr = new ActiveXObject(versions[i]); arguments.callee.activeXString = versions[i]; return xhr; }catch (ex){ //code } } } return new ActiveXObject(arguments.callee.activeXString); }else{ throw new Error("No XHR object available."); } } //按扭响应函数:创建xhr对象并进行相应操作 function loadXMLDoc(){ var xhr = new createXHR(); xhr.onreadystatechange = function(){ if(xhr.readyState == 4){ if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){ alert("statusText is "+xhr.statusText); alert("responseText is "+xhr.responseText); alert("responseXML is "+xhr.responseXML); alert("status is "+xhr.status); }else{ alert("Request was unsuccessful:" + xhr.status); } } }; xhr.open("get",true); xhr.setRequestHeader("Accept","90arther"); xhr.send(); } </script> </head> <body> <h2>AJAX</h2> <button type="button" onclick="loadXMLDoc()">请求数据</button> <div id="myDiv"></div> </body> </html> 四 、GET请求 GET是最常用的请求类型,最常用于向服务器查询某些信息。对于XHR而言,位于传入open()方法的URL末尾的查询字符串必须经过正确的编码才行。 1、查询字符串中的每个参数的名称和值必须使用encodeURIComponent()进行编码,然后才能放到URL的末尾,而且所有名-值对都必须由和号(&)分隔,如下面的例子所示: xhr.open("get","example.php?name1=value1&name2=value2",true);2、下面这个函数可以辅助向现有URL的末尾添加查询字符串的参数,这个函数接受三个参数:要添加参数的URL、参数的名称和参数的值。这个函数首先检查URL是否包含问号(以确定是否已经有参数存在)。如果没有,就添加一个问号;否则,就添加一个和号。然后,将参数名称和值进行编码,再添加到URL的末尾。最后返回添加参数之后的URL。 function addURLParam(url,name,value){ url += (url.indexOf("?")== -1?"?":"&"); url += encodeURIComponent(name) + "=" + encodeURIComponent(value); return url; } 3、下面是使用这个函数来构建请求URL的示例: var url = "example.php"; url = addURLParam(url,"name","Nicholas"); url = addURLParam(url,"Professional JavaScript"); //初始化请求 xhr.open("get",url,false);四、POST 请求 POST请求的主体可以包含非常多的数据,而且格式不限。在open()方法第一个参数的位置传入"post",就可以初始化一个POST请求,如下面的例子所示: xhr.open("post",true); 1、默认情况下,服务器对POST请求和提交表单的请求并不会一视同仁。因此,服务器端必须有程序来读取发送过来的原始数据,并从中解析出有用的部分。不过,我们可以使用XHR来模仿表单提交:首先将Content-Type头部信息设置为application/x-www-form-urlencoded,也就是表单提交时的内容类型,其次是以适当的格式 创建一个字符串。 function submitData(){ var xhr = createXHR(); xhr.onreadystatechange = function (event){ if(xhr.readyState == 4){ if((xhr.status >= 200 && xhr.status < 300)||xhr.status == 304){ alert(xhr.responseText); }else{ alert("Request was unsuccessful:"+ xhr.status); } } }; xhr.open("post","postexample.php",true); xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded"); var form = document.getElementById("user-info"); xhr.send(serialize(form)); }2、这个函数可以将ID为"user-info"的表单中的数据序列化之后发送给服务器,而下面的示例PHP文件postexample.php就可以通过$_POST取得提交的数据了。 <?php header("Content-Type:text/plain");//如果不设置Content-Type头部信息,那么发送给服务器的数据就不会出现在$_POST超级全局变量中。 echo <<<EOF Name:{$_POST['user-name']} Email:{$_POST['user-email']} EOF; ?> 五、浏览器差异 1、超时设定 IE8为XHR对象添加了一个timeout属性,表示请求在等待响应多少毫秒之后就终止。在给timeout设置一个数值后,如果在规定时间内浏览器还没有收到响应,那么就会触发timeout事件,进而会调用ontimeout事件处理程序。 var xhr = createXHR(); xhr.onreadystatechange = function(event){ try{ if(xhr.readyState == 4){ if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){ alert(xhr.responseText); }else{ alert("Request was unsuccessful:"+ xhr.status); } } }catch (ex){ //假设由ontimeout事件处理程序处理 } }; xhr.open("get","timeout.php",true); xhr.timeout = 1000; xhr.ontimeout = function(){ alert("Request did not not return in a second."); }; xhr.send(null); 2、加载(load)事件 Firefox实现中引入了load事件,用以替代readystatechange事件。响应接收完毕将触发load事件,因此也就没有必要去检查readyState属性了。而onload事件处理程序会接收一个event对象,其target属性就指向xhr对象实例,因而可以访问到XHR对象的所有方法和属性。然而,并非所有浏览器都这个事件实现了适当的事件对象。结果,开发人员还是要像下面这样被迫使用XHR对象变量: var xhr = createXHR(); xhr.onload = function (event){ if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){ alert(xhr.responseTest); }else{ alert("Request was unsuccessful:"+ xhr.status); } }; xhr.open("get","altevents.php",true); xhr.send(null); 只要浏览器接收到服务器的响应,不管其状态如何,都会触发load事件。而这意味着你必须要检查status属性,才能确定数据是否真的已经可用了。Firefox、Opera、Chrome和Safari都支持load事件。 3、进度(progress)事件Mozilla为XHR添加了progress事件(直到2008年,还没有其它浏览器实现这个特性)。 onprogress事件处理程序会接收到一个event对象,其target属性是XHR对象,但包含着两个额外的属性:position 和totalSiza。其中,position表示已经接收的字节数,totalSize表示根据content-length响应头部确定的预期字节数。 有了这些我们 就可以制作一个进度指示器了。 var xhr = createXHR(); xhr.onload = function(event){ if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){ alert(xhr.responseText); }else{ alert("Request was unsuccessful" + xhr.status); } }; xhr.onprogress = function(event){ var divStatus = document.getElementById("status"); divStatus.innerHTML = "Received" + event.position + "of" + event.totalSize + "bytes"; }; xhr.open("get","inc.txt",true); xhr.send(null); (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |