前端HTTP请求:Fetch API与Axios对比指南

📅 2026/7/18 6:59:31 👁️ 阅读次数 📝 编程学习
前端HTTP请求:Fetch API与Axios对比指南

1. 前端HTTP请求的两种主流方案

在现代前端开发中,HTTP请求是与后端交互的核心手段。目前主流方案主要有两种:浏览器原生提供的Fetch API和第三方库Axios。这两种方案各有特点,适用于不同的开发场景。

Fetch API作为现代浏览器原生支持的API,自2015年引入后逐渐成为标准。它基于Promise设计,语法简洁,无需额外安装依赖。而Axios作为一个成熟的HTTP客户端库,提供了更多高级功能和更完善的错误处理机制。

提示:选择哪种方案取决于项目需求。小型项目或简单请求可优先考虑Fetch,而复杂企业级应用可能更适合Axios。

2. Fetch API的核心特性与使用

2.1 基本请求示例

Fetch API的基本用法非常直观。以下是一个典型的GET请求示例:

fetch('https://api.example.com/data') .then(response => { if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } return response.json(); }) .then(data => console.log(data)) .catch(error => console.error('请求失败:', error));

Fetch使用Promise链式调用,第一个then处理响应状态,第二个then处理解析后的数据。需要注意的是,Fetch只有在网络故障时才会reject,HTTP状态码如404或500仍会resolve,因此需要手动检查response.ok。

2.2 POST请求与请求配置

发送POST请求时,需要配置method和body选项:

fetch('https://api.example.com/posts', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ title: '新文章', content: '这是文章内容' }) }) .then(response => response.json()) .then(data => console.log('创建成功:', data));

Fetch的配置对象支持多种选项,包括:

  • method: 请求方法(GET, POST等)
  • headers: 请求头
  • body: 请求体
  • mode: 请求模式(cors, no-cors等)
  • credentials: 是否发送cookie(include, same-origin等)

2.3 请求取消与超时处理

从ES2017开始,Fetch支持通过AbortController取消请求:

const controller = new AbortController(); const signal = controller.signal; // 设置5秒超时 const timeoutId = setTimeout(() => controller.abort(), 5000); fetch('https://api.example.com/data', { signal }) .then(response => response.json()) .then(data => { clearTimeout(timeoutId); console.log(data); }) .catch(err => { if (err.name === 'AbortError') { console.log('请求超时被取消'); } else { console.error('请求错误:', err); } });

3. Axios的核心优势与高级功能

3.1 基本请求示例

Axios提供了更简洁的API。同样的GET请求在Axios中更简单:

axios.get('https://api.example.com/data') .then(response => console.log(response.data)) .catch(error => { if (error.response) { // 服务器返回了错误状态码 console.log(error.response.status); console.log(error.response.data); } else if (error.request) { // 请求已发出但无响应 console.log(error.request); } else { // 其他错误 console.log('Error', error.message); } });

Axios自动将响应数据解析为JSON,并且对错误处理更加全面,能区分不同类型的错误。

3.2 拦截器功能

Axios的拦截器是其最强大的功能之一,允许你在请求或响应被then或catch处理前拦截它们:

// 添加请求拦截器 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); });

3.3 创建Axios实例

对于大型应用,可以创建多个Axios实例以适应不同的API端点:

const apiClient = axios.create({ baseURL: 'https://api.example.com', timeout: 5000, headers: { 'Content-Type': 'application/json', 'X-App-Version': '1.0.0' } }); // 使用实例 apiClient.get('/users') .then(response => console.log(response.data));

4. Fetch与Axios的深度对比

4.1 错误处理机制

Fetch和Axios在错误处理上有显著差异:

特性FetchAxios
网络错误自动reject自动reject
HTTP错误(4xx,5xx)仍会resolve,需手动检查自动reject
错误信息基本错误对象详细错误对象,含请求/响应信息

4.2 功能对比

两种方案的功能支持程度:

功能Fetch支持Axios支持
请求/响应拦截器需手动实现内置支持
请求取消通过AbortController内置支持
上传进度不支持支持
自动JSON转换需手动调用.json()自动转换
浏览器兼容性现代浏览器更广泛
请求超时需手动实现内置支持

4.3 性能与包大小

  • Fetch: 浏览器原生支持,零依赖
  • Axios: 约15KB(gzip压缩后),需要作为依赖引入

5. 实际项目中的选择建议

5.1 何时选择Fetch

以下情况适合使用Fetch:

  • 小型项目或简单请求
  • 希望避免额外依赖
  • 只需要基本HTTP功能
  • 项目运行在现代浏览器环境
  • 对包大小有严格要求

5.2 何时选择Axios

以下情况适合使用Axios:

  • 企业级复杂应用
  • 需要统一处理认证/错误
  • 需要上传进度跟踪
  • 项目需要兼容旧版浏览器
  • 需要与多个API端点交互

5.3 混合使用策略

在实际项目中,也可以考虑混合使用策略:

  • 主要使用Axios处理复杂请求
  • 在简单场景或需要极致轻量时使用Fetch
  • 通过封装统一两种方案的调用接口

6. 常见问题与解决方案

6.1 Fetch常见问题

问题1:为什么Fetch在404时仍进入then?

这是Fetch的设计特性。Fetch只会在网络故障时reject,HTTP错误状态仍会resolve。解决方案:

fetch(url) .then(response => { if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } return response.json(); })

问题2:如何用Fetch发送FormData?

const formData = new FormData(); formData.append('file', fileInput.files[0]); fetch('/upload', { method: 'POST', body: formData // 注意不要手动设置Content-Type,浏览器会自动处理 });

6.2 Axios常见问题

问题1:如何取消Axios请求?

Axios使用CancelToken(旧版)或AbortController(新版):

// 新版(推荐) const controller = new AbortController(); axios.get('/data', { signal: controller.signal }).catch(err => { if (axios.isCancel(err)) { console.log('请求取消:', err.message); } }); // 取消请求 controller.abort('用户取消操作');

问题2:如何处理并发请求?

Axios提供了axios.all和axios.spread:

const request1 = axios.get('/users'); const request2 = axios.get('/posts'); axios.all([request1, request2]) .then(axios.spread((usersRes, postsRes) => { console.log('用户:', usersRes.data); console.log('文章:', postsRes.data); }));

7. 高级技巧与最佳实践

7.1 封装统一的HTTP模块

无论是使用Fetch还是Axios,都建议封装统一的HTTP模块:

// http.js import axios from 'axios'; const http = axios.create({ baseURL: process.env.API_BASE_URL, timeout: 10000 }); // 请求拦截 http.interceptors.request.use(config => { // 添加认证token const token = getAuthToken(); if (token) { config.headers.Authorization = `Bearer ${token}`; } return config; }); // 响应拦截 http.interceptors.response.use( response => response.data, error => { // 统一错误处理 if (error.response) { switch (error.response.status) { case 401: redirectToLogin(); break; case 403: showForbiddenMessage(); break; // 其他状态码处理 } } return Promise.reject(error); } ); export default http;

7.2 类型安全(TypeScript)

在使用TypeScript时,可以为请求和响应定义类型:

interface User { id: number; name: string; email: string; } // 获取用户 export function getUser(id: number): Promise<User> { return http.get(`/users/${id}`); } // 创建用户 export function createUser(user: Omit<User, 'id'>): Promise<User> { return http.post('/users', user); }

7.3 性能优化

  • 请求缓存:对于不常变化的数据,实现请求缓存
  • 请求去重:避免短时间内重复发送相同请求
  • 批量请求:合并多个小请求为一个批量请求
  • 懒加载:非关键请求延迟发送

8. 未来发展趋势

虽然Fetch和Axios是目前主流方案,但前端HTTP请求领域仍在发展:

  1. React Query/SWR:这些数据获取库在缓存和状态管理方面提供了更高级的抽象
  2. GraphQL客户端:如Apollo Client,为GraphQL API提供了专门解决方案
  3. WebSocket/SSE:对于实时应用,这些协议提供了更好的实时性
  4. Service Worker:允许拦截和缓存网络请求,实现离线功能

在实际项目中,我通常会根据项目规模和复杂度做出选择。对于大多数中小型项目,Axios提供的便利性值得引入这个额外依赖。而在需要极致轻量或现代浏览器专有的PWA项目中,Fetch可能是更好的选择。