JavaScript请求数据的四种方法详解
1. XMLHttpRequest (Ajax)
基本概念
XMLHttpRequest 是浏览器提供的原生 API,用于在后台与服务器交换数据,是实现 Ajax (Asynchronous JavaScript and XML) 的核心技术。
基本使用
// 创建 XMLHttpRequest 对象
const xhr = new XMLHttpRequest();
// 配置请求
xhr.open('GET', 'https://api.example.com/data', true); // true 表示异步
// 设置请求头(可选)
xhr.setRequestHeader('Content-Type', 'application/json');
// 处理响应
xhr.onload = function() {
if (xhr.status >= 200 && xhr.status < 300) {
const response = JSON.parse(xhr.responseText);
console.log('成功:', response);
} else {
console.error('错误:', xhr.statusText);
}
};
xhr.onerror = function() {
console.error('请求失败');
};
// 发送请求
xhr.send();
POST 请求示例
const xhr = new XMLHttpRequest();
xhr.open('POST', 'https://api.example.com/data', true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.onload = function() {
if (xhr.status >= 200 && xhr.status < 300) {
console.log('响应:', JSON.parse(xhr.responseText));
}
};
const data = { name: 'John', age: 30 };
xhr.send(JSON.stringify(data));
优缺点
优点:
- 原生支持,无需第三方库
- 兼容性好,支持所有现代浏览器和旧版浏览器
- 支持进度事件(上传/下载进度)
缺点:
- API 设计复杂,回调嵌套多
- 不支持 Promise
- 代码冗长,可读性差
2. jQuery Ajax
基本概念
jQuery 是一个流行的 JavaScript 库,提供了简化的 Ajax 方法,封装了 XMLHttpRequest 的复杂性。
基本使用
// GET 请求
$.ajax({
url: 'https://api.example.com/data',
method: 'GET',
dataType: 'json',
success: function(response) {
console.log('成功:', response);
},
error: function(xhr, status, error) {
console.error('错误:', error);
}
});
// 简化的 GET 方法
$.get('https://api.example.com/data', function(response) {
console.log('成功:', response);
});
// POST 请求
$.post('https://api.example.com/data',
{ name: 'John', age: 30 },
function(response) {
console.log('成功:', response);
}
);
更完整的示例
$.ajax({
url: 'https://api.example.com/data',
method: 'POST',
dataType: 'json',
contentType: 'application/json',
data: JSON.stringify({ name: 'John', age: 30 }),
headers: {
'Authorization': 'Bearer token123'
},
beforeSend: function(xhr) {
console.log('请求发送前');
},
success: function(response, status, xhr) {
console.log('成功:', response);
},
error: function(xhr, status, error) {
console.error('错误:', error);
},
complete: function(xhr, status) {
console.log('请求完成');
}
});
优缺点
优点:
- API 简单易用
- 支持多种数据类型(JSON、XML、HTML、script)
- 内置错误处理
- 支持全局 Ajax 事件
- 良好的浏览器兼容性处理
缺点:
- 需要引入整个 jQuery 库(体积较大)
- 在现代前端开发中逐渐被替代
- 回调函数方式,不是 Promise 风格
3. Fetch API
基本概念
Fetch API 是现代浏览器提供的原生 API,基于 Promise 设计,提供了更强大、更灵活的功能。
基本使用
// GET 请求
fetch('https://api.example.com/data')
.then(response => {
if (!response.ok) {
throw new Error('网络响应不正常');
}
return response.json();
})
.then(data => {
console.log('数据:', data);
})
.catch(error => {
console.error('错误:', error);
});
// 使用 async/await
async function getData() {
try {
const response = await fetch('https://api.example.com/data');
if (!response.ok) {
throw new Error('网络响应不正常');
}
const data = await response.json();
console.log('数据:', data);
} catch (error) {
console.error('错误:', error);
}
}
POST 请求示例
fetch('https://api.example.com/data', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer token123'
},
body: JSON.stringify({
name: 'John',
age: 30
})
})
.then(response => response.json())
.then(data => console.log('成功:', data))
.catch(error => console.error('错误:', error));
高级功能
// 超时处理
function fetchWithTimeout(url, options = {}, timeout = 5000) {
return Promise.race([
fetch(url, options),
new Promise((_, reject) =>
setTimeout(() => reject(new Error('请求超时')), timeout)
)
]);
}
// 发送 FormData
const formData = new FormData();
formData.append('username', 'john');
formData.append('avatar', fileInput.files[0]);
fetch('https://api.example.com/upload', {
method: 'POST',
body: formData
});
// 取消请求(AbortController)
const controller = new AbortController();
const signal = controller.signal;
fetch('https://api.example.com/data', { signal })
.then(response => response.json())
.then(data => console.log(data))
.catch(err => {
if (err.name === 'AbortError') {
console.log('请求被取消');
}
});
// 取消请求
controller.abort();
优缺点
优点:
- 原生支持,无需第三方库
- 基于 Promise,支持 async/await
- 更简洁的 API 设计
- 支持请求/响应流
- 内置请求取消功能
缺点:
- 默认不会携带 cookie,需要配置 credentials
- 错误处理不如 Axios 直观(需要检查 response.ok)
- 不支持超时设置(需要手动实现)
- 部分旧版浏览器不支持
4. Axios
基本概念
Axios 是一个基于 Promise 的 HTTP 客户端,可用于浏览器和 Node.js,提供了丰富的功能和配置选项。
基本使用
// 安装:npm install axios
// GET 请求
axios.get('https://api.example.com/data')
.then(response => {
console.log('数据:', response.data);
})
.catch(error => {
console.error('错误:', error);
});
// POST 请求
axios.post('https://api.example.com/data', {
name: 'John',
age: 30
}, {
headers: {
'Content-Type': 'application/json'
}
})
.then(response => {
console.log('响应:', response.data);
});
完整配置示例
// 创建实例
const instance = axios.create({
baseURL: 'https://api.example.com',
timeout: 5000,
headers: { 'X-Custom-Header': 'foobar' }
});
// 使用实例
instance.get('/users')
.then(response => console.log(response.data));
// 并发请求
axios.all([
axios.get('https://api.example.com/users'),
axios.get('https://api.example.com/posts')
])
.then(axios.spread((usersResponse, postsResponse) => {
console.log('用户:', usersResponse.data);
console.log('文章:', postsResponse.data);
}));
// 请求拦截器
axios.interceptors.request.use(
config => {
// 在发送请求前做些什么
config.headers.Authorization = `Bearer ${localStorage.getItem('token')}`;
return config;
},
error => {
// 对请求错误做些什么
return Promise.reject(error);
}
);
// 响应拦截器
axios.interceptors.response.use(
response => {
// 对响应数据做点什么
return response;
},
error => {
// 对响应错误做点什么
if (error.response?.status === 401) {
// 处理未授权
window.location.href = '/login';
}
return Promise.reject(error);
}
);
优缺点
优点:
- 基于 Promise,支持 async/await
- 客户端和服务器端均可使用
- 丰富的配置选项
- 自动转换 JSON 数据
- 请求/响应拦截器
- 内置 CSRF 保护
- 取消请求功能
- 超时处理
- 下载进度支持
缺点:
- 需要额外安装(约 13KB)
- 对于简单请求可能过于重量级
比较表格
| 特性 |
XMLHttpRequest |
jQuery Ajax |
Fetch API |
Axios |
|---|
| Promise 支持 |
否 |
否(但可包装) |
是 |
是 |
| async/await |
否 |
否 |
是 |
是 |
| 浏览器支持 |
所有浏览器 |
所有浏览器 |
现代浏览器 |
现代浏览器 + polyfill |
| 请求取消 |
是 |
是 |
是(AbortController) |
是 |
| 超时设置 |
是 |
是 |
否(需手动实现) |
是 |
| 拦截器 |
否 |
是(全局事件) |
否 |
是 |
| 自动 JSON |
否 |
是 |
是(需调用 .json()) |
是 |
| 上传进度 |
是 |
是 |
否 |
是 |
| CSRF 保护 |
手动 |
是 |
手动 |
是 |
| 体积 |
0KB(原生) |
~30KB(jQuery) |
0KB(原生) |
~13KB |
使用建议
简单项目/原型开发:使用 Fetch API(现代浏览器)或 XMLHttpRequest(兼容性要求高)
已有 jQuery 的项目:继续使用 jQuery Ajax
现代前端应用:推荐使用 Axios(功能全面)或 Fetch API(轻量级需求)
Node.js 环境:Axios(最常用)或 node-fetch(Fetch API 的实现)
示例:同功能不同实现
// 获取用户列表的四种实现方式
// 1. XMLHttpRequest
function getUsersXHR() {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open('GET', 'https://api.example.com/users');
xhr.onload = () => resolve(JSON.parse(xhr.responseText));
xhr.onerror = reject;
xhr.send();
});
}
// 2. jQuery
function getUsersjQuery() {
return $.ajax({
url: 'https://api.example.com/users',
method: 'GET',
dataType: 'json'
});
}
// 3. Fetch API
async function getUsersFetch() {
const response = await fetch('https://api.example.com/users');
return response.json();
}
// 4. Axios
async function getUsersAxios() {
const response = await axios.get('https://api.example.com/users');
return response.data;
}
总结
选择哪种方法取决于项目需求:
- 兼容性最重要:XMLHttpRequest 或 jQuery
- 现代应用,功能全面:Axios
- 轻量级,现代浏览器:Fetch API
- 已有 jQuery 项目:继续使用 jQuery Ajax
在实际开发中,Axios 因其功能全面和易于使用而成为当前最受欢迎的选择,特别是对于需要复杂HTTP交互的应用程序。