XMLHttpRequest 是一个内建的浏览器对象,它允许使用 JavaScript 发送 HTTP 请求。
虽然我们已经有了更现代的fetch方法,但是我们需要做一些 fetch 目前无法做到的事情,例如跟踪上传进度。
Get请求
一个XMLHttpRequest的使用示例
// 1. 创建一个 new XMLHttpRequest 对象
// 此构造器没有参数
let xhr = new XMLHttpRequest();
// 2. 配置它:从 URL /article/.../load GET-request
// 注意open并不会发送请求
// xhr.open(method, URL, [async, user, password])
xhr.open('GET', '/article/xmlhttprequest/example/load');
// 3. 通过网络发送请求
xhr.send();
// 4. 当接收到响应后,将调用此函数
xhr.onload = function() {
if (xhr.status != 200) { // 分析响应的 HTTP 状态
alert(`Error ${xhr.status}: ${xhr.statusText}`); // 例如 404: Not Found
} else { // 显示结果
alert(`Done, got ${xhr.response.length} bytes`); // response 是服务器响应
}
};
xhr.onprogress = function(event) {
if (event.lengthComputable) {
alert(`Received ${event.loaded} of ${event.total} bytes`);
} else {
alert(`Received ${event.loaded} bytes`); // 没有 Content-Length
}
};
xhr.onerror = function() {
alert("Request failed");
};
一旦服务器有了响应,我们可以在以下 xhr 属性中接收结果:
- statusHTTP 状态码(一个数字):200,404,403 等,如果出现非 HTTP 错误,则为 0。
- statusText HTTP 状态消息(一个字符串):状态码为 200 对应于 OK,404 对应于 Not Found,403 对应于 Forbidden。
- response(旧脚本可能用的是 responseText)服务器 response body。
我们可以使用 xhr.responseType 属性来设置响应格式
xhr.responseType = 'json';
XMLHttpRequest 的状态(state)会随着它的处理进度变化而变化。可以通过 xhr.readyState 来了解当前状态。
UNSENT = 0; // 初始状态
OPENED = 1; // open 被调用
HEADERS_RECEIVED = 2; // 接收到 response header
LOADING = 3; // 响应正在被加载(接收到一个数据包)
DONE = 4; // 请求完成
我们可以使用 readystatechange 事件来跟踪它们:
xhr.onreadystatechange = function() {
if (xhr.readyState == 3) {
// 加载中
}
if (xhr.readyState == 4) {
// 请求完成
}
};
我们可以随时终止请求。调用 xhr.abort()
即可
如果在 open
方法中将第三个参数 async
设置为 false
,那么请求就会以同步的方式进行。
换句话说,JavaScript 执行在 send()
处暂停,并在收到响应后恢复执行。这有点儿像 alert
或 prompt
命令
POST请求
要建立一个 POST 请求,我们可以使用内建的 FormData 对象。
语法为:
let formData = new FormData([form]); // 创建一个对象,可以选择从 <form> 中获取数据
formData.append(name, value); // 附加一个字段
let xhr = new XMLHttpRequest();
let json = JSON.stringify({
name: "John",
surname: "Smith"
});
xhr.open("POST", '/submit')
// 设置requestHeader
xhr.setRequestHeader('Content-type', 'application/json; charset=utf-8');
xhr.send(json);
上传进度
如果我们需要专门跟踪上传,那么我们应该在 xhr.upload 对象上监听相同的事件。
<input type="file" onchange="upload(this.files[0])">
<script>
function upload(file) {
let xhr = new XMLHttpRequest();
// 跟踪上传进度
xhr.upload.onprogress = function(event) {
console.log(`Uploaded ${event.loaded} of ${event.total}`);
};
// 跟踪完成:无论成功与否
xhr.onloadend = function() {
if (xhr.status == 200) {
console.log("success");
} else {
console.log("error " + this.status);
}
};
xhr.open("POST", "/article/xmlhttprequest/post/upload");
xhr.send(file);
}
</script>