ajax-XHR对象

来源:互联网 发布:手机安装电视软件 编辑:程序博客网 时间:2024/04/29 23:42

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.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);}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","example.php",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","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);}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","test.txt",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","example.php",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 <<<EOFName:{$_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);




原创粉丝点击