1. 为什么考虑替代 axios在前端开发中axios 长期以来都是处理 HTTP 请求的首选库。但现代浏览器原生提供的 Fetch API 已经足够强大能够满足大多数场景的需求。使用原生 API 最直接的好处就是减少项目依赖降低打包体积。根据实测在典型项目中移除 axios 可以减少 10-15KB 的打包体积gzip 后。原生 Fetch API 从 2015 年就开始被主流浏览器支持目前所有现代浏览器都已实现。特别是在需要支持现代浏览器的项目中完全没有必要额外引入 HTTP 请求库。我最近在一个新项目中完全使用 Fetch API 替代 axios发现开发体验几乎没有差别反而因为减少了抽象层调试起来更加直观。2. Fetch API 基础用法解析2.1 发起 GET 请求最基本的 GET 请求非常简单fetch(https://api.example.com/data) .then(response response.json()) .then(data console.log(data)) .catch(error console.error(Error:, error));与 axios 不同的是Fetch API 返回的 Promise 不会直接 reject HTTP 错误状态如 404 或 500。需要手动检查 response.ok 属性fetch(https://api.example.com/data) .then(response { if (!response.ok) { throw new Error(HTTP error! status: ${response.status}); } return response.json(); }) // ...2.2 发起 POST 请求POST 请求需要额外配置 options 参数fetch(https://api.example.com/data, { method: POST, headers: { Content-Type: application/json, }, body: JSON.stringify({ key: value }) }) .then(response response.json()) // ...3. 高级功能实现3.1 请求超时处理Fetch API 本身没有内置超时功能但可以通过 Promise.race 实现const timeout (ms) new Promise((_, reject) setTimeout(() reject(new Error(Request timeout)), ms) ); Promise.race([ fetch(https://api.example.com/data), timeout(5000) ]) .then(response response.json()) // ...3.2 取消请求使用 AbortController 可以取消正在进行的请求const controller new AbortController(); const signal controller.signal; fetch(https://api.example.com/data, { signal }) .then(response response.json()) // ... // 取消请求 controller.abort();3.3 上传进度监控对于大文件上传可以通过读取 ReadableStream 来监控进度const response await fetch(https://api.example.com/upload, { method: POST, body: largeFile, }); const reader response.body.getReader(); let receivedLength 0; while(true) { const {done, value} await reader.read(); if (done) break; receivedLength value.length; console.log(Received ${receivedLength} bytes); }4. 与 axios 的功能对比4.1 功能差异对照表功能Fetch APIaxios浏览器支持现代浏览器所有浏览器请求取消需要 AbortController内置支持超时处理需要手动实现内置支持自动转换 JSON需要手动调用 .json()自动转换拦截器无有上传/下载进度需要手动实现内置支持CSRF 防护需要手动设置内置支持请求/响应转换无有4.2 何时应该坚持使用 axios虽然 Fetch API 很强大但在以下场景可能还是需要 axios需要支持非常旧的浏览器IE11 及以下项目已经重度依赖 axios 的拦截器功能需要开箱即用的上传/下载进度监控团队对 axios 有很强的熟悉度切换成本过高5. 常见问题与解决方案5.1 处理 CORS 问题Fetch API 默认的 credentials 策略与 axios 不同。如果需要发送 cookies需要显式设置fetch(https://api.example.com/data, { credentials: include })5.2 错误处理最佳实践建议封装一个统一的错误处理函数async function fetchWithErrorHandling(url, options) { try { const response await fetch(url, options); if (!response.ok) { const error new Error(response.statusText); error.response response; throw error; } return await response.json(); } catch (error) { // 统一错误处理逻辑 console.error(Fetch error:, error); throw error; } }5.3 性能优化技巧复用 Headers 对象const headers new Headers(); headers.append(Content-Type, application/json); // 后续请求可以复用这个 headers 对象使用 keepalive 标志提升页面卸载时的请求可靠性fetch(/analytics, { method: POST, body: analyticsData, keepalive: true });6. 实际项目迁移经验我在最近的项目中从 axios 迁移到 Fetch API总结了一些实用经验渐进式迁移可以先在新功能中使用 Fetch API逐步替换旧代码封装工具函数根据项目需求封装几个常用的 fetch 工具函数类型安全如果是 TypeScript 项目为 fetch 响应添加类型注解测试覆盖确保所有边界情况都有测试覆盖特别是错误处理一个实用的 TypeScript 封装示例interface FetchOptions extends RequestInit { timeout?: number; } async function enhancedFetchT any( url: string, options: FetchOptions {} ): PromiseT { const { timeout 8000, ...fetchOptions } options; const controller new AbortController(); const { signal } controller; const timeoutId setTimeout(() controller.abort(), timeout); try { const response await fetch(url, { ...fetchOptions, signal }); if (!response.ok) { throw new Error(HTTP error! status: ${response.status}); } return await response.json(); } finally { clearTimeout(timeoutId); } }7. 生态系统补充虽然 Fetch API 是浏览器原生功能但有些场景下可能需要一些辅助工具fetch-retry为 fetch 添加自动重试功能cross-fetch提供一致的 Node.js 和浏览器 fetch 实现redaxios模仿 axios API 的轻量级 fetch 封装对于大多数项目来说这些工具都不是必需的原生 Fetch API 已经足够强大。只有在特定需求下才需要考虑引入这些辅助库。
阅读完成 · 觉得有帮助?