目前原生Ajax和.ajax已经形式猛如虎。这一技术能够向服务器请求额外的数据而无须卸载页面,会带来更好的用户体验。Ajax技术的核心是XMLHttpRequest对象,这是由微软首先引入的一种特性,其他浏览器供应商后来都提供了相同的实现。在重命名为Ajax之后,大约是2005年底2006年初,这种浏览器与服务器的通信技术可谓是红极一时。人们对Javascript和Web的全新认识,催生了很多使用原有特性的新技术和新模式。就目前来说,熟悉使用XHR对象已经成为所有Web开发人员必须掌握的一种技能。

最早在IE5中,XHR对象是通过MSXML库中的一个ActiveX对象实现的。要使用MSXML库中的XHR对象,想支持IE7以及更高版本,需要编写一个函数:

function createXHR(){
    if (typeof XMLHttpRequest !== 'undefined') {
       return new XMLHttpRequest();
    }
    // IE7及以下
    else if (typeof ActiveXObject !== 'undefined') {
            if (typeof arguments.callee.activeXString !== 'string') {
                const versions = ['MSXML2.XMLHttp.6.0','MSXML2.XNLHttp.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(e) {
                            // statements
                        }
                    }
                }
                return new ActiveXObject(arguments.callee.activeXString);
            } else {
              throw new Error("NO XHR object available.");
            }
        }

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

const xhr = createXHR();

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

xhr.open('get','http://120.78.164.247:9999/user/findAll', false);

这行代码会启动一个针对http://120.78.164.247:9999/user/findAll的GET请求。要发送特定的请求,必须像下面这样调用send()方法:

xhr.open('get','http://120.78.164.247:9999/user/findAll', false);
xhr.send(null);

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

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

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

像前面这样发送同步请求当然没有问题,但多数情况下,我们还是要求发送异步请求,才能让JavaScript继续执行而不必等待响应。此时,可以检测XHR对象的readyState属性,该属性表示请求/响应过程的当前活动阶段。只要readyState属性的值由一个值变成另一个值,都会触发一次readystatechange事件。可以利用这个事件来检测每次状态变化后readyState的值。通常,我们只对readyState值为4的阶段感兴趣,因为这时所有数据都已经就绪。不过,必须在调用open()之前指定onreadystatechange事件处理程序才能确保跨浏览器兼容性。下面来看一个例子:

const xhr = createXHR();
xhr.onreadystatechange = () => {
    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','http://120.78.164.247:9999/user/findAll', false);
xhr.send(null);

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


cheneyg
88 声望2 粉丝

心有猛虎,细嗅蔷薇