
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只有在网络故障时才会rejectHTTP状态码如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自动rejectHTTP错误(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只会在网络故障时rejectHTTP错误状态仍会resolve。解决方案fetch(url) .then(response { if (!response.ok) { throw new Error(HTTP error! status: ${response.status}); } return response.json(); })问题2如何用Fetch发送FormDataconst 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.spreadconst 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): PromiseUser { return http.get(/users/${id}); } // 创建用户 export function createUser(user: OmitUser, id): PromiseUser { return http.post(/users, user); }7.3 性能优化请求缓存对于不常变化的数据实现请求缓存请求去重避免短时间内重复发送相同请求批量请求合并多个小请求为一个批量请求懒加载非关键请求延迟发送8. 未来发展趋势虽然Fetch和Axios是目前主流方案但前端HTTP请求领域仍在发展React Query/SWR这些数据获取库在缓存和状态管理方面提供了更高级的抽象GraphQL客户端如Apollo Client为GraphQL API提供了专门解决方案WebSocket/SSE对于实时应用这些协议提供了更好的实时性Service Worker允许拦截和缓存网络请求实现离线功能在实际项目中我通常会根据项目规模和复杂度做出选择。对于大多数中小型项目Axios提供的便利性值得引入这个额外依赖。而在需要极致轻量或现代浏览器专有的PWA项目中Fetch可能是更好的选择。