翻译:《javascript : The Definitive Guide,5th Edition》
英文:《异步交互(二)》
一、XMLHttpRequest对象获取
XMLHttpRequest对象详解:3个构造方法,5个属性,6个方法,1个事件——3561详解AJAX核心对象XMLHttpRequest。
约定1:本文中所有的xhr指代XMLHttpRequest对象。
约定2:问了方便介绍该对象,本文并没有原原本本的按照英文翻译。
二、构造方法
1. 几乎适用所有浏览器
new XMLHttpRequest();
2. 适用IE 7+
new ActiveXObject("Msxml2.XMLHTTP");
3. 适用IE 5,IE 6
new ActiveXObject("Microsoft.XMLHTTP");
补充
new XMLHttpRequest();创建xhr对象,适用于chrome、Firefox、opera以及IE 7+等浏览,也就意味着第一种和第二种构造方,只需要选用第一种就可以了,所以为了最保险的方式,三种都用,但实际上只需要第一种和第三种构造方法配合使用就可以了。具体创建方法请看《异步交互(一)》(早期完备方式,三种构造方法均使用)或查询w3cschool示例源码xhr对象创建(新的创建xhr对象方式,使用第一种和第三种构造方法)。
三、属性详解
1. readyState
只读属性,返回值类型short。
该属性表示xhr对象的状态,状态值从0(当该对象第一次被创建的时候,readyState为0)开始一直增加到4(当收到完整的HTTP响应的时候,该属性值为4),一般情况下,readyState对应的状态值只会增加会不减少,除非调用了abort()方法,或是一个已经在异步交互进程中的xhr对象再次调用了open()方法。
每一次状态值的增加,都会触发onreadystatechange事件,因此可以通过该事件来对整个异步交互过程进行控制。
readyState属性对应的5个状态各都有一个非正式的名字,下面将详细介绍readyState对象。
----------------------------------------------------------------------------------------------------------------------------
状态值 状态名 描述
0 Uninitialized 初始化状态,表示xhr对象已经被成功创建,或者一个已经存在的xhr对象调用了abort()方法进行了重置
1 Open 建立连接的状态,调用了open方法,但是还没有调用send方法,request对象还未被发送
2 Send 发送状态,send方法已经被调用,http请求已经被提交给了服务器,但是还未收到来自服务器的任何响应信息
3 Receiving 表示接收响应中,已经收到所有的响应消息头,但是还没有完整的收到响应消息
4 Loaded 完成状态,已经收到了所有的响应消息,xhr对象完成交互一次交互过程
----------------------------------------------------------------------------------------------------------------------------
2. responseText
自读属性,返回值类型String。
表示从远端服务器返回的响应体的内容(不包含响应头,响应的结构请参看点击打开链接),如果没有收到数据,则该属性为空字符串。通常情况下,如果readyState的状态值小于3,则该属性的值为空字符串;如果readyState的状态值刚好为3,那么该属性的值为当前已经从服务器获得的响应体的数据,尽管获得的数据可能只是完整响应中的部分数据;如果readyState的状态值为4,那么该属性表示完整的响应体数据。
重要:关于数据编码,如果响应头中包含有字符编码信息(譬如Context-type中的charset),则responseText属性的值使用该编码方式;否则默认使用UTF-8进行数据编码。
3. responseXML
只读属性,返回值类型Document。
请求对应的返回数据被当作XML进行解析,解析完成后返回一个Document对象,这意味着从服务器返回的数据应该要复合xml格式,否则解析失败。
要想该属性的返回值不为null,必须满足以下三个条件(三个都为真,则该属性的值不为null,否则为null):
a. xhr的状态值readyState为4;
b. 返回的响应头信息中明确包含该该响应是一个XML文档的响应头信息,譬如Context-type的值为”text/xml;charset=UTF-8",或为“application/xml”,或其他能够表明该响应是一个XML文档的响应头;
c. 响应体的内容应该是满足一个XML格式的数据,确保按照XML格式进行解析的时候不会出错,也就意味着服务器返回的数据就是一个XML文档;
补充:
推荐使用XStream,第三方jar包将对象解析成XML串然后返回给服务器,官网:XStream,官网上有代码示例,是简洁。
4. status
只读属性,返回值类型short。
服务器返回的响应状态码,表示服务器响应的状态,譬如200,404等。
注意:如果在xhr状态值小于3(不包含3)的情况下读取该状态值,则会抛出一个异常。
5. statusText
只读属性,返回值类型String。
服务器返回的响应状态码描述,譬如status=200,则statusText=“OK",这两个属性都由HTTP协议规定。
注意:如果在xhr状态值小于3(不包含3)的情况下读取该状态值,则会抛出一个异常。
四、方法详解
1. abort
返回值void。该方法取消当前的请求,调用该方法,会产生以下操作:
a. 会关闭连接并停止xhr对象当前一切网络活动;
b. 重置xhr对象的readyState值为0;
使用场景:如果xhr对象发出的请求已经过了很长时间还未收到响应,或者通过调用该方法你可以关闭一个没有必要的异步请求。
2. open
返回值void。该方法只对HTTP请求对象进行参数初始化,例如请求方式、URL等。
参数:void open(String method,String url,boolean async,String username,String password);
method表示HTTP请求方式,常用的有GET和POST;url表示请求的url,如果是get方式,则参数需要写在后面,如果是post方式,则参数通过send方法发送;async表示选择异步交互还是同步交互,如果该值为true或缺省,则为异步交互方式,如果该值为true,则表示为同步交互方式,此时客户端浏览器会被请求阻塞,直到收到响应对象为止,这种方式和传统的交互方式一致;如果服务器需要认证,则通过username和password进行传值认证。
注意:仅当xhr的readyState为0或4的时候调用该方法是安全的,其他状态下调用该方法结果未明确。
该方法应该在调用send方法之前被调用,调用该方法会产生以下操作:
a. 初始化request参数,删掉之前的所有请求头和响应头;
b. 将xhr的readyState状态值设置为1;
c. 将responseText,responseXML,status,statusText设为默认值;
d. 该方法会不会和服务器建立一个网络连接;
注意:
a. 当xhr对象的readyState状态值为0或4的时候,调用该方法是安全的,此时该方法会将请求参数和xhr对象的属性重置为默认值;
b. 当采用post方式建立连接的时候,在建立连接之后和发送请求之前,需要设置请求头Context-type,否则服务器抛出异常或不能正常进行数据接收和处理。设置方式如下代码示例。
//POST方式向服务器传送数据 document.getElementById("username").onblur = function(){ var username = this.value; if(username == null || username == "") return; var xhr = getXhr(); xhr.onreadystatechange = function(){ if(xhr.readyState == 4){ if(xhr.status == 200){ document.getElementById("unInfo").innerHTML = xhr.responseText; } } } xhr.open("POST","${pageContext.request.contextPath}/checkUN"); //post方式,在建立连接之后需要设置context-type请求头 //1. 如果是普通的表单提交:xhr.setRequestHeader("content-type","application/x-www-form-urlencoded"); //2. 如果是文件上传:xhr.setRequestHeader("content-type","multipart/form-data"); xhr.setRequestHeader("content-type","application/x-www-form-urlencoded"); xhr.send("username="+username); }
3. send
返回值void。void send(Object obj)。
如果在open方法中采用的GET或POST方法进行连接,则obj可以为一个字符串或一个文档对象,否则参数obj应该为null;如果是采用GET方式,则send方法中传送的值服务器端是收不到的,只能附在url后面。
调用该方法会发送一个请求,如果此时xhr对象的状态值不为1,则会抛出一个异常,调用该方法,会产生以下操作:
a. 发送请求,并将xhr对象的readyState状态值设为2(出发onreadystatechange事件);
b. 如果async参数为false,那么调用该方法之后将会立即阻塞浏览器进程,并一直等到xhr的状态为4的时候才会返回;如果async参数为true,那么调用该方法则在发送参数之后立即返回,由一个后台线程和服务器进行交互;
c. 如果服务器响应是一个重定向,那么send方法(同步情况下)或后台线程(异步情况下)将会自动进行重定向操作;
d. 当收到所有的响应头之后,会设置readyState的值为3,当完成相应的时候,会将readyState的值设为4;
4. setRequestHeader
只是设置或添加一个HTTP请求头,不会导致请求对象重置。
参数:void setRequestHeader(String name,String value);
name为请求头名字,value为值,如果该请求头已经存在,则重置其value,否则视为添加请求头。
注意:该方法已经改在readyState为1的时候调用,即应该在open建立连接但是还未send请求对象之间被调用。
5. getResponseHeader
获取响应头的值。
参数:String getResponseHeader(String name);
返回响应头name对应的value,如果没有该响应头,则返回空字符串。
6. getAllResponseHeaders
获取所有响应头的值。
参数:String getAllResponseHeaders();
注意:如果xhr对象的readyState状态值小于3,则返回null;否则,该方法会以一个字符串的形式返回响应对象包含的所有响应头信息,不同的响应头(name和value)之间通过“\r\n”来进行分割。
五、事件详解
xhr对象有且仅有一个事件onreadystatechange,注意所有字母都是小写的,javascript和Java一样都是区分大小写的。
每一次xhr对象的readyState状态值改变都会触发该事件,但是该方法不能为单独的一个xhr对象绑定多个事件处理逻辑,即onreadystatechange只能绑定一个事件处理的function,如果你想处理多件事情,那么只能在绑定的function中进行多事件处理的逻辑调用。
//一个xhr对象的onreadystatechange事件只能绑定一个function //如果多次绑定,则最后一次绑定的function覆盖之前绑定的function //如果想进行多件事情的处理,那么应该在绑定的function中进行其他方法的调用 xhr.onreadystatechange = function(){ if(xhr.readyState == 4){ if(xhr.status == 200){ document.getElementById("unInfo").innerHTML = xhr.responseText; } } }
附注:
本文如有错漏,烦请不吝指正,谢谢!
本文翻译自javascript第五版,并没有原原本本的按照英文原书进行翻译,如果有错漏的地方,烦请指正!