`XMLHttpRequest`(通常缩写为XHR)是一个JavaScript对象,用于在浏览器和服务器之间进行异步通信。它允许网页在不重新加载整个页面的情况下,向服务器发送请求并接收响应。XHR是Ajax(Asynchronous JavaScript and XML)技术的核心组成部分,广泛用于现代Web应用中,以实现动态内容加载、表单提交、数据验证等功能。
XHR最初由微软在Internet Explorer 5中引入,后来被其他浏览器广泛支持,并成为Web标准的一部分。尽管它的名字中包含“XML”,但它并不局限于处理XML数据,实际上可以处理任何类型的数据,包括JSON、HTML、纯文本等。
### XMLHttpRequest的工作原理
1. **创建XHR对象**:首先,你需要创建一个`XMLHttpRequest`对象。
2. **配置请求**:使用XHR对象的`open()`方法配置请求的类型(GET、POST等)、URL以及是否异步。
3. **设置回调函数**:通过`onreadystatechange`事件处理器或`onload`、`onerror`等事件处理器来定义请求完成后的处理逻辑。
4. **发送请求**:使用`send()`方法发送请求。如果是POST请求,可以在`send()`方法中传递请求体数据。
5. **处理响应**:当服务器返回响应时,XHR对象会触发相应的事件,你可以在回调函数中处理响应数据。
### XMLHttpRequest的基本用法
以下是一个简单的XHR示例,展示了如何向服务器发送GET请求并处理响应。
```javascript
// 1. 创建XMLHttpRequest对象
var xhr = new XMLHttpRequest();
// 2. 配置请求
xhr.open('GET', 'https://jsonplaceholder.typicode.com/posts/1', true);
// 3. 设置回调函数
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) { // 请求完成
if (xhr.status === 200) { // 成功响应
console.log('Response:', xhr.responseText);
} else {
console.error('Error:', xhr.statusText);
}
}
};
// 4. 发送请求
xhr.send();
```
### XMLHttpRequest的属性和方法
#### 属性
- **readyState**:表示请求的状态,取值范围为0到4:
- 0:未初始化(`open()`尚未调用)
- 1:已打开(`open()`已调用,但`send()`尚未调用)
- 2:已发送(`send()`已调用,响应尚未接收)
- 3:接收中(响应部分接收)
- 4:完成(响应完全接收)
- **status**:HTTP状态码,如200表示成功,404表示未找到等。
- **statusText**:HTTP状态文本,如"OK"、"Not Found"等。
- **responseText**:响应体作为字符串返回。
- **responseXML**:响应体作为XML文档返回(如果响应内容是XML)。
- **response**:响应体,类型取决于`responseType`的设置。
#### 方法
- **open(method, url, async)**:初始化请求。
- `method`:请求类型,如"GET"、"POST"等。
- `url`:请求的URL。
- `async`:是否异步,默认为`true`。
- **send(body)**:发送请求。
- `body`:请求体数据,通常用于POST请求。
- **setRequestHeader(header, value)**:设置请求头。
- `header`:请求头名称。
- `value`:请求头值。
- **abort()**:中止请求。
### 处理不同类型的响应
XHR可以处理多种类型的响应数据,包括JSON、XML、HTML等。你可以通过设置`responseType`属性来指定期望的响应类型。
#### 处理JSON响应
```javascript
var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://jsonplaceholder.typicode.com/posts/1', true);
xhr.responseType = 'json'; // 指定响应类型为JSON
xhr.onload = function() {
if (xhr.status === 200) {
console.log('Response:', xhr.response); // 直接获取JSON对象
} else {
console.error('Error:', xhr.statusText);
}
};
xhr.send();
```
#### 处理XML响应
```javascript
var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://example.com/data.xml', true);
xhr.responseType = 'document'; // 指定响应类型为XML文档
xhr.onload = function() {
if (xhr.status === 200) {
var xmlDoc = xhr.responseXML;
var title = xmlDoc.getElementsByTagName('title')[0].textContent;
console.log('Title:', title);
} else {
console.error('Error:', xhr.statusText);
}
};
xhr.send();
```
### 发送POST请求
XHR不仅可以发送GET请求,还可以发送POST请求,通常用于提交表单数据或发送JSON数据。
```javascript
var xhr = new XMLHttpRequest();
xhr.open('POST', 'https://jsonplaceholder.typicode.com/posts', true);
xhr.setRequestHeader('Content-Type', 'application/json'); // 设置请求头
xhr.onload = function() {
if (xhr.status === 201) { // 201表示创建成功
console.log('Response:', xhr.responseText);
} else {
console.error('Error:', xhr.statusText);
}
};
var data = JSON.stringify({
title: 'foo',
body: 'bar',
userId: 1
});
xhr.send(data); // 发送JSON数据
```
### 错误处理
XHR请求可能会因为网络问题、服务器错误等原因失败。你可以通过`onerror`事件处理器来处理这些错误。
```javascript
var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://example.com/nonexistent', true);
xhr.onload = function() {
if (xhr.status === 200) {
console.log('Response:', xhr.responseText);
} else {
console.error('Error:', xhr.statusText);
}
};
xhr.onerror = function() {
console.error('Request failed');
};
xhr.send();
```
### 跨域请求
XHR默认遵循同源策略,即只能向同一域名、端口和协议的URL发送请求。如果需要跨域请求,可以使用CORS(跨域资源共享)或JSONP(仅限GET请求)。
#### 使用CORS
服务器需要设置`Access-Control-Allow-Origin`响应头,允许特定的域名或所有域名(`*`)访问资源。
```javascript
var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://another-domain.com/data', true);
xhr.onload = function() {
if (xhr.status === 200) {
console.log('Response:', xhr.responseText);
} else {
console.error('Error:', xhr.statusText);
}
};
xhr.send();
```
### 总结
`XMLHttpRequest`是Web开发中非常重要的工具,它使得网页能够在不重新加载的情况下与服务器进行通信。尽管现代开发中更常用`fetch` API或第三方库(如Axios)来处理HTTP请求,但理解XHR的工作原理仍然是非常有价值的。通过本文的介绍和示例代码,你应该能够掌握XHR的基本用法,并在实际项目中灵活运用。