跳转到内容

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仍十分重要,因为:

  1. 它被所有浏览器完全支持(包括旧版本)
  2. 许多遗留代码仍使用XHR
  3. 它提供了Fetch目前缺乏的某些功能(如进度事件)

基本用法[编辑 | 编辑源代码]

创建XHR对象[编辑 | 编辑源代码]

所有现代浏览器都通过XMLHttpRequest构造函数支持XHR:

const xhr = new XMLHttpRequest();

配置请求[编辑 | 编辑源代码]

使用open()方法初始化请求:

xhr.open(method, url, async);

参数说明:

  • method: HTTP方法(如"GET"、"POST"等)
  • url: 请求目标URL
  • async: 是否异步执行(默认为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。