JavaScript XMLHttpRequest
XMLHttpRequest(通常缩写为XHR)是JavaScript中用于与服务器交互的核心API之一,允许在不刷新页面的情况下发送HTTP请求和接收响应。它是现代AJAX(Asynchronous JavaScript and XML)技术的基础,尽管名称中包含"XML",但它支持多种数据格式(如JSON、HTML或纯文本)。
概述[编辑 | 编辑源代码]
XMLHttpRequest对象提供了一种在客户端和服务器之间传输数据的机制。通过XHR,开发者可以:
- 从服务器获取数据(GET请求)
- 向服务器发送数据(POST/PUT/DELETE等请求)
- 异步或同步处理响应
- 监控请求进度(如文件上传)
虽然现代开发更常用Fetch API或第三方库(如Axios),但理解XHR仍十分重要,因为:
- 它被所有浏览器完全支持(包括旧版本)
- 许多遗留代码仍使用XHR
- 它提供了Fetch目前缺乏的某些功能(如进度事件)
基本用法[编辑 | 编辑源代码]
创建XHR对象[编辑 | 编辑源代码]
所有现代浏览器都通过XMLHttpRequest
构造函数支持XHR:
const xhr = new XMLHttpRequest();
配置请求[编辑 | 编辑源代码]
使用open()
方法初始化请求:
xhr.open(method, url, async);
参数说明:
method
: HTTP方法(如"GET"、"POST"等)url
: 请求目标URLasync
: 是否异步执行(默认为true)
示例:
// 异步GET请求
xhr.open('GET', 'https://api.example.com/data', true);
发送请求[编辑 | 编辑源代码]
使用send()
方法发送请求。对于GET请求通常为空,POST请求可包含数据:
// GET请求
xhr.send();
// POST请求
xhr.send(JSON.stringify({ key: 'value' }));
处理响应[编辑 | 编辑源代码]
通过事件监听器处理响应:
xhr.onload = function() {
if (xhr.status >= 200 && xhr.status < 300) {
console.log('成功:', xhr.response);
} else {
console.error('错误:', xhr.statusText);
}
};
xhr.onerror = function() {
console.error('请求失败');
};
完整示例[编辑 | 编辑源代码]
以下是一个完整的XHR示例,从JSON API获取数据:
const xhr = new XMLHttpRequest();
xhr.open('GET', 'https://jsonplaceholder.typicode.com/posts/1', true);
xhr.onload = function() {
if (this.status === 200) {
const response = JSON.parse(this.responseText);
console.log('Received:', response);
// 输出示例:
// {
// "userId": 1,
// "id": 1,
// "title": "...",
// "body": "..."
// }
} else {
console.error('Error:', this.statusText);
}
};
xhr.onerror = function() {
console.error('Request failed');
};
xhr.send();
高级特性[编辑 | 编辑源代码]
设置请求头[编辑 | 编辑源代码]
使用setRequestHeader()
方法:
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.setRequestHeader('Authorization', 'Bearer token123');
注意:必须在open()
之后、send()
之前调用。
处理超时[编辑 | 编辑源代码]
设置超时时间(毫秒)和对应事件:
xhr.timeout = 5000; // 5秒超时
xhr.ontimeout = function() {
console.error('请求超时');
};
跟踪进度[编辑 | 编辑源代码]
XHR提供了进度事件,特别适用于大文件上传/下载:
xhr.upload.onprogress = function(event) {
if (event.lengthComputable) {
const percent = (event.loaded / event.total) * 100;
console.log(`上传进度: ${Math.round(percent)}%`);
}
};
xhr.onprogress = function(event) {
// 下载进度处理
};
同步请求[编辑 | 编辑源代码]
虽然不推荐(会阻塞UI线程),但XHR支持同步请求:
xhr.open('GET', '/data', false); // 第三个参数为false
xhr.send();
// 代码会在此等待响应
if (xhr.status === 200) {
console.log(xhr.responseText);
}
状态管理[编辑 | 编辑源代码]
XHR对象有个readyState
属性,表示请求状态:
值 | 状态 | 描述 |
---|---|---|
0 | UNSENT | 代理被创建,但尚未调用open()方法 |
1 | OPENED | open()方法已经被调用 |
2 | HEADERS_RECEIVED | send()方法已经被调用,并且头部和状态已经可获得 |
3 | LOADING | 下载中;responseText属性已经包含部分数据 |
4 | DONE | 下载操作已完成 |
可通过onreadystatechange
事件跟踪状态变化:
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.responseText);
}
};
实际应用案例[编辑 | 编辑源代码]
案例1:表单提交[编辑 | 编辑源代码]
使用XHR提交表单数据而无需页面刷新:
document.getElementById('myForm').addEventListener('submit', function(e) {
e.preventDefault();
const xhr = new XMLHttpRequest();
const formData = new FormData(this);
xhr.open('POST', '/submit-form', true);
xhr.onload = function() {
if (this.status === 200) {
alert('表单提交成功!');
}
};
xhr.send(formData);
});
案例2:实时搜索[编辑 | 编辑源代码]
实现输入时实时搜索建议:
const searchInput = document.getElementById('search');
searchInput.addEventListener('input', function() {
const xhr = new XMLHttpRequest();
xhr.open('GET', `/search?q=${encodeURIComponent(this.value)}`, true);
xhr.onload = function() {
if (this.status === 200) {
const results = JSON.parse(this.responseText);
displayResults(results); // 自定义函数显示结果
}
};
xhr.send();
});
与Fetch API的比较[编辑 | 编辑源代码]
特性 | XMLHttpRequest | Fetch API |
---|---|---|
语法 | 基于事件回调 | 基于Promise |
流式读取 | 不支持 | 支持 |
请求取消 | 支持 | 通过AbortController |
进度事件 | 支持 | 不完全支持 |
同步请求 | 支持 | 不支持 |
浏览器支持 | 所有浏览器 | 现代浏览器 |
安全考虑[编辑 | 编辑源代码]
使用XHR时需注意:
- 同源策略:默认只能访问同源(相同协议、域名和端口)资源
- CORS:跨域请求需要服务器设置适当的CORS头
- CSRF防护:对状态修改请求使用CSRF令牌
- HTTPS:生产环境始终使用HTTPS
常见问题[编辑 | 编辑源代码]
为什么我的请求被阻止了?[编辑 | 编辑源代码]
可能是由于: 1. 违反同源策略且未正确配置CORS 2. 服务器未返回正确的CORS头(如Access-Control-Allow-Origin) 3. 请求需要认证但未提供凭据
解决方案:
- 对于简单请求,服务器应返回:
Access-Control-Allow-Origin: *
- 对于带凭据的请求:
xhr.withCredentials = true;
且服务器响应需包含:
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: [具体域名,不能为*]
如何中止请求?[编辑 | 编辑源代码]
调用abort()
方法:
xhr.abort(); // 中止请求
xhr.onabort = function() {
console.log('请求被中止');
};
最佳实践[编辑 | 编辑源代码]
1. 始终处理错误事件(onerror)
2. 对于JSON响应,使用JSON.parse()
前检查有效性
3. 设置合理的超时时间
4. 必要时添加Loading状态指示器
5. 考虑使用try-catch处理意外错误
6. 清理不再需要的XHR对象以避免内存泄漏
总结[编辑 | 编辑源代码]
XMLHttpRequest是JavaScript中进行HTTP通信的基础API。虽然现代开发中Fetch API更为流行,但XHR仍因其广泛的浏览器支持、进度事件等特性而保持重要地位。理解XHR的工作原理有助于开发者更好地处理网络请求,维护遗留代码,以及在需要特定功能时做出适当选择。
通过本指南,您应该已经掌握了XHR的核心概念、基本用法、高级特性以及实际应用场景。建议通过实际项目练习来巩固这些知识,并逐步探索更现代的替代方案如Fetch API。