在前端开发中,网络请求是与服务器交互的基础。本文将详细介绍三种常用的JavaScript网络请求方法:XMLHttpRequest (Ajax)、Axios和Fetch API,帮助你理解它们的特点和适用场景,从而选择最适合自己项目的网络通信方案。
1. XMLHttpRequest (原生Ajax)
XMLHttpRequest是最原始的网络请求方法,所有现代浏览器都支持它。尽管它看起来有些"古老",但了解它有助于理解其他网络请求方法的基础原理。
GET请求
// 创建XMLHttpRequest对象
const xhr = new XMLHttpRequest();
// 配置请求
xhr.open('get', 'https://api.example.com/data?name=user&age=18');
// 发送请求
xhr.send();
// 监听响应
xhr.onreadystatechange = function() {
// 方法一:详细判断
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
console.log(xhr.response);
} else {
console.log('请求失败');
}
}
// 方法二:简洁判断
if(xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
console.log(JSON.parse(xhr.responseText));
}
};
说明:
readyState有5个值:- 0: 未初始化
- 1: 已打开
- 2: 已发送
- 3: 接收中
- 4: 已完成
XMLHttpRequest.DONE等于4,表示请求已完成status是HTTP状态码,200表示成功
POST请求
const xhr = new XMLHttpRequest();
// 配置POST请求
xhr.open('post', 'https://api.example.com/submit');
// 设置请求头,告诉服务器内容类型
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
// 发送数据
xhr.send('name=user&age=18');
// 监听响应
xhr.onreadystatechange = function() {
if(xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
console.log(JSON.parse(xhr.responseText));
}
};
POST请求注意事项:
- 需要设置
Content-Type请求头 - 数据在
send()方法中传递 - 常见的
Content-Type值:application/x-www-form-urlencoded:表单数据application/json:JSON数据multipart/form-data:文件上传
2. Axios
Axios是一个基于Promise的HTTP客户端,可以在浏览器和Node.js中使用。它是目前最流行的网络请求库之一,提供了简洁易用的API和丰富的功能。
基本使用
// GET请求
axios.get('https://api.example.com/data?name=user&age=18')
.then(response => {
console.log(response.data);
})
.catch(error => {
console.error('请求出错', error);
});
// 带参数的GET请求
axios.get('https://api.example.com/data', {
params: {
name: 'user',
age: 18
}
})
.then(response => {
console.log(response.data);
});
// POST请求
axios.post('https://api.example.com/submit', {
name: 'user',
age: 18
})
.then(response => {
console.log(response.data);
});
创建实例
创建Axios实例可以设置基本配置,便于复用:
const api = axios.create({
baseURL: 'https://api.example.com',
timeout: 1000,
headers: {'X-Custom-Header': 'foobar'}
});
// 使用实例发送请求
api.get('/data', {
params: {
name: 'user',
age: 18
}
})
.then(response => {
console.log(response.data);
});
拦截器
Axios拦截器可以在请求发送前和响应接收后进行处理,非常适合添加认证信息、统一错误处理等场景:
// 请求拦截器
api.interceptors.request.use(config => {
// 在请求发送前做些什么
console.log('发送了请求');
// 可以添加认证信息、修改请求配置等
config.headers.Authorization = `Bearer ${localStorage.getItem('token')}`;
return config;
}, error => {
// 请求错误处理
return Promise.reject(error);
});
// 响应拦截器
api.interceptors.response.use(response => {
// 在获取响应数据前做些什么
console.log('收到响应');
// 可以统一处理响应数据
return response;
}, error => {
// 响应错误处理
if (error.response.status === 401) {
// 处理未授权错误
console.log('未授权,请重新登录');
}
return Promise.reject(error);
});
使用async/await
使用async/await可以让Axios请求代码更加简洁易读:
async function fetchData() {
try {
// GET请求
const response = await api.get('/data', {
params: {
name: 'user',
age: 18
}
});
// POST请求
const submitResponse = await api.post('/submit', {
name: 'user',
age: 18
});
console.log(response.data);
console.log(submitResponse.data);
} catch (error) {
console.error('请求出错', error);
}
}
fetchData();
3. Fetch API
Fetch API是现代浏览器原生支持的网络请求API,基于Promise设计,提供了一个更简洁的接口来发送和接收网络请求。
基本使用
// 基 本GET请求
fetch('https://api.example.com/data?name=user&age=18')
.then(response => {
if (response.ok) {
return response.json();
}
throw new Error('请求失败');
})
.then(data => {
console.log(data);
})
.catch(error => {
console.error('错误:', error);
});
处理响应
Fetch返回的Response对象有多种方法处理不同类型的响应:
fetch('https://api.example.com/data')
.then(response => {
// 检查响应状态
if (!response.ok) {
throw new Error(`HTTP错误! 状态: ${response.status}`);
}
// 根据内容类型选择不同的处理方法
// response.json() - 解析JSON
// response.text() - 获取文本
// response.blob() - 获取二进制数据
// response.formData() - 获取表单数据
// response.arrayBuffer() - 获取ArrayBuffer
return response.json();
})
.then(data => {
console.log(data);
});
发送POST请求
fetch('https://api.example.com/submit', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
// 'Content-Type': 'application/x-www-form-urlencoded' 用于表单数据
},
body: JSON.stringify({
name: 'user',
age: 18
})
})
.then(response => {
if (response.ok) {
return response.json();
}
throw new Error('请求失败');
})
.then(data => console.log(data))
.catch(error => console.error('错误:', error));
注意: 使用application/json时,需要用JSON.stringify()处理数据;使用application/x-www-form-urlencoded时,可以使用URLSearchParams或手动拼接字符串 。
使用async/await
使用async/await可以让Fetch代码更加简洁:
async function fetchData() {
try {
const response = await fetch('https://api.example.com/data');
if (!response.ok) {
throw new Error(`HTTP错误! 状态: ${response.status}`);
}
const data = await response.json();
console.log(data);
} catch (error) {
console.error('获取数据失败:', error);
}
}
fetchData();
取消请求
Fetch API可以使用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(error => {
if (error.name === 'AbortError') {
console.log('请求被取消');
} else {
console.error('请求失败:', error);
}
});
// 取消请求
setTimeout(() => controller.abort(), 5000); // 5秒后取消请求
4. 三种方法的比较
| 特性 | XMLHttpRequest | Axios | Fetch API |
|---|---|---|---|
| 浏览器支持 | 所有现代浏览器 | 所有现代浏览器 (需引入库) | 现代浏览器 (IE 不支持) |
| 基于 Promise | 否 | 是 | 是 |
| 请求取消 | 支持 | 支持 | 有限支持 (AbortController) |
| 请求超时 | 支持 | 支持 | 不直接支持 (需结合 Promise.race) |
| 自动转换 JSON | 否 | 是 | 需手动调用 .json() |
| 拦截器 | 否 | 是 | 否 |
| 下载进度 | 支持 | 支持 | 有限支持 |
| CSRF 保护 | 手动实现 | 自动支持 | 手动实现 |