使用XMLHttpRequest
浏览器在XMLHttpRequest类上定义了它们的HTTP API。
这个类的每个实例都表示一个独立的请求/响应对,并且这个对象的属性和方法允许指定请求细节和提取响应的数据。
使用这个HTTP API必须做的第一件事就是实例化XMLHttpRequest对象:
var request = new XMLHttpRequest();
也能重用已存在的XMLHttpRequest,但注意这将会终止之前通过该对象挂起的任何请求。
一个HTTP请求由4部分组成:
- HTTP请求方法或动作
- 正在请求的URL
- 一个可选的请求头集合,其中可能奥阔身份验证信息
- 一个可选的请求主体
服务器返回的HTTP响应包含3部分:
- 一个数字和文字组成的状态吗,用来显示请求的成功和失败
- 一个响应头集合
- 响应主体
指定/发送请求
创建XMLHttpRequest对象之后,发起HTTP请求的下一步是调用XMLHttpRequest对象的open()方法去指定这个请求的两个必须部分:方法和URL。
例如:
request.open("GET", "data.csv");
如果有请求头的话,请求进程的下个步骤是设置它。例如:
request.setRequestHeader("Content-Type", "text/plain");
如果对相同的头调用setRequestHeader多次,新值不会取代之前指定的值,相反,HTTP请求将包含这个头的多个副本或这个头将指定多个值。
不能自己指定 Content-Length, Date , Referer ,User-Agent 头,XMLHttpRequest将自动添加这头而防止伪造它们。XMLHttpRequest对象自动处理cookie,连接时间,字符集和编码判断,所以无法向setRequestHeader()传递这些头:
Accept-Charset Content-Transfer-Encoding TE
Accept-Encoding Date Trailer
Connection Expect Transfer-Encoding
Content-Length Host Upgrade
Cookie Keep-Alive User-Agent
Cookie2 Referer Via
使用XMLHttpRequest发起HTTP请求的最后一步是指定可选的请求主体并向服务器发送它。使用send()方法:
request.send(null);
注意各方法的调用顺序。
例如:
function postMessage(msg){var request = new XMLHttpRequest();request.open("POST","/log.php");// 用请求主体发送纯文本消息request.setRequestHeader("Content-Type", "text/plain;charset=UTF-8");request.send(msg);
}
取得/获取响应
一个完整的HTTP响应由状态码,响应头集合和响应主体组成。
这些可以通过XMLHttpRequest对象的属性和方法使用:
- status和statusText属性以数字和文本的形式返回HTTP状态码。这些属性保存标准的HTTP值,像200和”OK“表示成功请求,404和”Not Found“表示URL不能匹配服务器上的任何资源。
- 使用getResponseHeader()和getAllResponseHeaders()能查询响应头,XMLHttpRequest会自动处理cookie,它会从getAllResponseHeaders()返回集合中过滤掉cookie头,而如果给getResponseHeader()传递”Set-Cookie“和”Cookie2“则返回null
- 响应主体可以从responseText属性中得到文本形式的,从responseXML属性中得到Document形式的
XMLHttpRequest对象通常异步使用:
发送请求后,send()方法立即返回,直到响应返回,前面列出的响应方法和属性才有效。
为了在响应准备就绪时得到通知,必须监听XMLHttpRequest对象上的 readystatechange 事件。
readyState是一个整数,它指定了HTTP请求的状态,下表是可能的值。第一列的符号是XMLHttpRequest构造函数定义的常量,
常量 | 值 | 含义 |
UNSENT | 0 | open()尚未使用 |
OPENED | 1 | open()已调用 |
HEADERS_RECEIVED | 2 | 接受到头信息 |
LOADING | 3 | 接受到响应主体 |
DONE | 4 | 响应完成 |
每次readyState属性改变都会触发readystatechange事件。
为了监听readystatechange事件,请把事件处理函数设置为XMLHttpRequest对象的onreadysatechange属性。也能使用addEventListerner(),但通常每个请求只需要一个处理程序。
例如:
function getText(url, callback){var request = new XMLHttpRequest();request.open("GET", url);request.onreadystatechange = function(){if (request.readyState === 4 && request.status === 200){var type = request.getResponseHeader("Content-Type");if (type.match(/^text/)){callback(request.responseText);}}};request.send(null);
}
同步响应
异步处理HTTP响应是最好的方式,然而,XMLHttpRequest也支持同步响应。
如果把false作为第3个参数传递给open(),那么send()方法将阻塞直到请求完成。在这种情况下,不需要使用事件处理程序:一旦send()返回,仅需要检查XMLHttpRequest对象的status和responseText属性。
同步请求会阻塞。
响应解码
服务器使用像”text/plain“, "text/html", "text/css"这样的MIME类型发送文本响应,然后使用XMLHttpRequest对象的responseText属性得到它。
如果服务器发送XML或XHTML文档作为其响应,能通过responseXML属性获得一个解析形式的XML文档。这个属性的值是一个Document对象。
JSON:
如果服务器向发送诸如对象或数组这样的结构化数据作为其响应,它应该传输JSON编码的字符串数据。当接收它时,可以把responseText属性传递给JSON.parse()。
例如:
... ...
var type = request.getResponseHeader("Content-Type");
if (type.indexOf("xml") !== -1 && request.responseXML)callback(request.responseXML);
else if (type === "application/json")callback(JSON.parse(request.responseText));
elsecallback(request.responseText);
... ...
请求主体的编码
HTTP POST请求包括一个请求主体,它包含客户端传递给服务器的数据。通常使用HTTP请求发送的都是更复杂的数据。
表单编码的请求
HTML表单,当用户提交表单时,表单中的数据编码到一个字符串中并随着请求发送。
默认情况下,HTML表单通过POST方法发送给服务器,而编码后的表单数据则用作请求主体。对表单数据使用的编码方案相对简单:对每个表单元素的名字和值执行普通的URL编码,使用等号把编码后的名字和值分开,并使用 & 符号分开名/值对。例如:
find=pizz&zipcode=02134&radius=1km
当使用POST方法提交这种顺序的表单数据时,必须设置”Content-Type“请求头为:
application/x-www-form-urlencoded
JSON编码的请求
使用JSON.stringify(),例如:
... ...
request.setRequestHeader("Content-Type", "application/json");
request.send(JSON.stringify(data));
... ...
XML编码的请求
XMLHttpRequest的send()方法的参数是一个字符串或null。实际上,可以在这里传入XML Document对象。
上传文件
multipart/form-data请求
当HTML表单同时包含文件上传元素和其他元素时,浏览器不能使用普通的表单编码而必须使用称为”multipart/form-data“的特殊Content-Type来用POST方法提交表单。
HTTP进度事件
响应加载进度事件
请求上传进度事件
中止请求和超时
可以通过调用XMLHttpRequest对象的abort()方法来取消正在进行的HTTP请求。调用abort()方法在这个对象上触发abort事件。
可以用setTimeout()和abort()方法实现自己的超时。
跨域HTTP请求