XMLHttpRequest对象
除IE以外所有的浏览器都支持直接使用XMLHttpRequest对象。而IE是通过创建ActiveXObject来创建类似的对象。这里给出一种包装方法使得IE5以上的IE版本也能具有XMLHttpRequest对象,这样我们在使用XMLHttpRequest对象的时候可以使用同一的创建方法:
(来自《精通JavaScript》)
if
(
typeof
XMLHttpRequest
==
'
undefined
'
) {
XMLHttpRequest
=
function
() {
return
new
ActiveXObject(
navigator.userAgent.indexOf(
"
MSIE 5
"
)
>=
0
?
"
Microsoft.XMLHTTP
"
:
"
Msxml2.XMLHTTP
"
);
}
}
发送请求
GET请求
只支持发送串行化数据(下文会有具体例子)
以下是GET请求发送的简单例子
//
创建对象
var
xml
=
new
XMLHttpRequest();
//
初始化
xml.open(
"
GET
"
,
"
test.html
"
,
true
);
//
发送
xml.send();
POST请求
POST请求发送方式与GET请求发送方式类似,下文具体。
请求状态
我们可以通过XMLHttpRequest对象中的readyState监视请求的状态。readyState是一个整型值,各自代表的状态是:
0 = 未初始化
1 = 已初始化 (有些书将此状态注为下载,实际测试发现初始化后、未发送请求之前,状态已经修改为1)
2 = 下载已完成
3 = 交互的(响应被部分接收)
4 = 完成
在我们的Ajax应用中,一般只需要使用4-完成状态。
当请求状态变化时,会触发onreadystatechange事件,我们处理ajax响应就是为这个事件绑定处理函数。
客户端完整示例
以下结合上述内容,写一个完整的客户端ajax示例
var
xml
=
new
XMLHttpRequest();
//
未初始化 xml.readyState 为 0
xml.open(
"
POST
"
,
"
test.html
"
,
true
);
//
已初始化 xml.readyState 为 1
xml.setRequestHeader(
"
Content-Type
"
,
"
application/x-www-form-urlencoded
"
);
if
(xml.overrideMimeType)
xml.setRequestHeader(
"
Connection
"
,
"
close
"
);
//
绑定状态变化事件处理函数
xml.onreadystatechange
=
function
() {
alert(xml.readyState);
}
xml.send(
"
abc
"
);
数据对象的格式
根据数据对象的特点,我们可以选择合适的发送方式。
串行化
利用HTTP GET标准请求,即类似: http://www.zhengchuyu.cn/?name=zcy&nick=donald 的传输方式。
我们需要有一个串行化函数,并且是针对表单元素和键值对对象设计的。(不能串行化多选按钮)
function
serialize(a) {
var
s
=
[];
if
(a.constructor
==
Array) {
//
表单元素数组
for
(
var
i
=
0
; i
<
a.length; i
++
) {
s.push( a[i].name
+
"
=
"
+
encodeURIComponent(a[i].value));
}
}
else
{
//
键值对对象
for
(
var
j
in
a)
s.push(j
+
"
=
"
+
encodeURIComponent(a[j]));
}
return
s.join(
"
&
"
);
}
GET请求发送串行化数据
var
xml
=
new
XMLHttpRequest();
xml.open(
"
GET
"
,
"
test.html?
"
+
serialize(data),
true
);
xml.send();
POST请求发送串行化数据
var
xml
=
new
XMLHttpRequest();
xml.open(
"
POST
"
,
"
test.html
"
,
true
);
//
设置content-type头部信息,告诉服务器如何解析我们发送的数据
xml.setRequestHeader(
"
Content-Type
"
,
"
application/x-www-form-urlencoded
"
);
//
保证浏览器发送的串行化数据长度正确
if
(xml.overrideMimeType)
xml.setRequestHeader(
"
Connection
"
,
"
close
"
);
//
串行化数据发送
xml.send(serialize(data));
xml
后文详述。
json
后文详述
HTTP响应
上文已经提到可以通过判断readyState的值得知请求状态,我们可以知道客户端是否已经获得了服务器响应。但是服务器并不是每一次都能正常响应,这时我们需要通过服务器响应代码(保存在返回结果对象的status变量中)判断响应情况。
状态码
成功响应 200~300
未修改响应 304
本地文件 无状态码
另外有一个特殊情况(来自《精通JavaScript》,没有验证),Safari浏览器中,如果文档自上次请求未曾修改过,会返回状态码“undefined”,比较怪异。
以下给出一判断XMLHttpRequest对象是否处于成功响应状态的兼容函数
function
httpSuccess(r) {
try
{
return
!
r.status
&&
location.protocol
==
"
file:
"
||
(r.status
>=
200
&&
r.status
<
300
)
||
r.status
==
304
||
navigator.userAgent.indexOf(
"
Safari
"
)
>=
0
&&
typeof
r.status
==
"
undefined
"
;
}
catch
(e) {
return
false
;
}
}
超时检查
超时检查比较简单,就是用一个变量记录是否超时,在send发送之前用一个setTimeout设定在某个时间段后把该变量标记为超时,并在状态改变响应函数中检测这一变量就行了。
服务器返回数据
服务器可以返回任何格式的数据。一般比较常用的是XML、HTML、JavaScript/JSON。
获取数据
获取数据通过XMLHttpRequest的两个重要属性:responseXML和responseText。
responseXML 可以获取XML,即服务器明确指出“Content-Type:text/xml”时才可以由这个属性获取。
responseText 可以获取HTML和JavaScript类型的数据。
指定类型解析数据
以下是一个按指定类型解析数据的函数
(来自《精通JavaScript》,为了便于理解,稍有改动)
//
type可选值:xml, script, text, html 默认值:空
function
httpData(r, type) {
var
ct
=
r.getResponseHeader(
"
content-type
"
);
var
data
=
!
type
&&
ct
&&
ct.indexOf(
"
xml
"
)
>=
0
;
data
=
(type
==
"
xml
"
||
data)
?
r.responseXML : r.responseText;
if
(type
==
"
script
"
)
eval.call(window, data);
return
data;
}