您当前的位置:首页 > 网站建设笔记 >

JavaScript的XMLHttpRequest对象及用法

来源:JavaScript高级程序设计(第3版)0

XMLHttpRequest 对象

IE5是第一款引入XHR对象的浏览器。在IE5中,XHR对象是通过 MSXML 库中的一个 ActiveX 对象实现的。因此,在IE中可能会遇到三种不同版本的XHR对象,即 MSXML2.XMLHttp、MSXML2.XMLHttp.3.0 和 MSXML2.XMLHttp.6.0。要使用 MSXML 库中的XHR对象,需要编写一个函数,例如:

<script type="text/javascript">
//适用于IE7之前的版本
function createXHR() {
    if (typeof arguments.callee.activeXString != "string") {
        var versions = ["MSXML2.XMLHttp.6.0",
                        "MSXML2.XMLHttp.3.0",
                        "MSXML2.XMLHttp"],i,len;
        for (i=0,len=versions.length; i<len; i++) {
            try {
                new ActiveXObject(versions[i]);
                arguments.callee.activeXString = versions[i];
                break;
            } catch (ex) {
                //跳过
            }
        }
    }
    return new ActiveXObject(arguments.callee.activeXString);
}
</script>

这个函数会尽力根据IE中可用的MSXML库的情况创建最新版本的XHR对象。

IE7+、Firefox、Opera、Chrome和Safari都支持原生的XHR对象,在这些浏览器中创建XHR对象要像下面这样使用XMLHttpRequest构造函数。

var xhr = new XMLHttpRequest();

假如你只想支持IE7及更高版本,那么大可丢掉前面定义的那个函数,而只用原生的XHR实现。但是,如果你必须还要支持IE的早期版本,那么则可以在这个createXHR()函数中加入对原生XHR对象的支持。

<script type="text/javascript">
function createXHR() {
    if (typeof XMLHttpRequest != "undefined") {
        return new XMLHttpRequest();
    } else if (typeof ActiveXObject != "undefined") {
        if (typeof arguments.callee.activeXString != "string") {
            var versions = ["MSXML2.XMLHttp.6.0",
                            "MSXML2.XMLHttp.3.0",
                            "MSXML2.XMLHttp"],i,len;
            for (i=0,len=versions.length; i<len; i++) {
                try {
                    new ActiveXObject(versions[i]);
                    arguments.callee.activeXString = versions[i];
                    break;
                } catch (ex) {
                    //跳过
                }
            }
        }
        return new ActiveXObject(arguments.callee.activeXString);
    } else {
        throw new Error("No XHR object available");
    }
}
</script>

这个函数中新增的代码首先检测原生XHR对象是否存在,如果存在则返回它的新实例。如果原生对象不存在,则检测ActiveX对象。如果这两种对象都不存在,就抛出一个错误。然后,就可以使用下面的代码在所有浏览器中创建XHR对象了。

var xhr = createXHR();

由于其他浏览器中对XHR的实现与IE最早的实现是兼容的,因此就可以在所有浏览器中都以相同方式使用上面创建的xhr对象。

XHR的用法

在使用XHR对象时,要调用的第一个方法是open(),它接受3个参数:要发送的请求的类型(get、post等)、请求的URL和表示是否异步发送请求的布尔值。下面就是调用这个方法的例子。

xhr.open("get","example.php",false);

这行代码会启动一个针对example.php的GET请求。有关这行代码,需要说明两点:一是URL相对于执行代码的当前页面(当然也可以使用绝对路径);二是调用open()方法并不会真正发送请求,而只是启动一个请求以备发送。

要发送特定的请求,必须像下面这样调用send()方法:
xhr.open("get", "example.php", false);
xhr.send(null);

这里的send()方法接收一个参数,即要作为请求主体发送的数据。如果不需要通过请求主体发送数据,则必须传入null,因为这个参数对有些浏览器来说是必需的。调用send()之后,请求就会被分派到服务器。

由于这次请求是同步的,JavaScript代码会等到服务器响应之后再继续执行。在收到响应后,响应的数据会自动填充XHR对象的属性,相关的属性简介如下。

  • responseText:作为响应主体被返回的文本。
  • responseXML:如果响应的内容类型是"text/xml"或"application/xml",这个属性中将保存包含着响应数据的XML DOM文档。
  • status:响应的HTTP状态。
  • statusText:HTTP状态的说明。

在接收到响应后,第一步是检查status属性,以确定响应已经成功返回。一般来说,可以将HTTP状态代码为200作为成功的标志。此时,responseText属性的内容已经就绪,而且在内容类型正确的情况下,responseXML也应该能够访问了。此外,状态代码为304表示请求的资源并没有被修改,可以直接使用浏览器中缓存的版本;当然,也意味着响应是有效的。为确保接收到适当的响应,应该像下面这样检查上述这两种状态代码:

xhr.open("get", "example.txt", false);
xhr.send(null);

if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
    alert(xhr.responseText);
} else {
    alert("Request was unsuccessful: " + xhr.status);  
}

根据返回的状态代码,这个例子可能会显示由服务器返回的内容,也可能会显示一条错误消息。我们建议读者要通过检测status来决定下一步的操作,不要依赖statusText,因为后者在跨浏览器使用时不太可靠。另外,无论内容类型是什么,响应主体的内容都会保存到responseText属性中;而对于非XML数据而言,responseXML属性的值将为null。

有的浏览器会错误地报告204状态代码。IE中XHR的ActiveX版本会将204设置为1223,而IE中原生的XHR则会将204规范化为200。Opera会在取得204时报告status的值为0。

像前面这样发送同步请求当然没有问题,但多数情况下,我们还是要发送异步请求,才能让JavaScript继续执行而不必等待响应。此时,可以检测XHR对象的readyState属性,该属性表示请求/响应过程的当前活动阶段。这个属性可取的值如下。

  • 0:未初始化。尚未调用open()方法。
  • 1:启动。已经调用open()方法,但尚未调用send()方法。
  • 2:发送。已经调用send()方法,但尚未接收到响应。
  • 3:接收。已经接收到部分响应数据。
  • 4:完成。已经接收到全部响应数据,而且已经可以在客户端使用了。

只要readyState属性的值由一个值变成另一个值,都会触发一次readystatechange事件。可以利用这个事件来检测每次状态变化后readyState的值。通常,我们只对readyState值为4的阶段感兴趣,因为这时所有数据都已经就绪。不过,必须在调用open()之前指定onreadystatechange事件处理程序才能确保跨浏览器兼容性。下面来看一个例子。

var xhr = createXHR();
xhr.onreadystatechange = function(){
    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("get", "example.txt", true);
xhr.send(null);

以上代码利用DOM 0级方法为XHR对象添加了事件处理程序,原因是并非所有浏览器都支持DOM 2级方法。与其他事件处理程序不同,这里没有向onreadystatechange事件处理程序中传递event对象;必须通过XHR对象本身来确定下一步该怎么做。

这个例子在onreadystatechange事件处理程序中使用了xhr对象,没有使用this对象,原因是onreadystatechange事件处理程序的作用域问题。如果使用this对象,在有的浏览器中会导致函数执行失败,或者导致错误发生。因此,使用实际的XHR对象实例变量是较为可靠的一种方式。

另外,在接收到响应之前还可以调用abort()方法来取消异步请求,如下所示:
xhr.abort();
调用这个方法后,XHR对象会停止触发事件,而且也不再允许访问任何与响应有关的对象属性。在终止请求之后,还应该对XHR对象进行解引用操作。由于内存原因,不建议重用XHR对象。

建站咨询

咨询热线

微信交流

返回顶部