[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"site-config":3,"article-axios学习笔记":22,"comments-axios学习笔记":43,"footer-socials":52},{"site_title":4,"site_subtitle":5,"home_intro":6,"avatar":7,"seo_keywords":8,"seo_description":9,"site_subtitle_highlight":10,"home_description":11,"about_name":12,"about_intro":13,"code_comment_2":14,"code_log":15,"code_skills":16,"code_goal":17,"code_comment_1":18,"meteor_density":19,"meteor_max_count":19,"meteor_enabled":20,"meteor_speed":21},"ShineGoldYao","架构代码，","全栈开发者 \u002F 开源爱好者 \u002F 技术探索者","https:\u002F\u002Fforuda.gitee.com\u002Favatar\u002F1762402862010015318\u002F16382196_yaoxingjin_1762402861.png!avatar200","ShiGoldYao,技术博客,全栈开发","专注于前沿技术分享与开源项目展示的个人技术博客","书写未来。","大家好，我是 ShiGoldYao。一名全栈学习与技术爱好者。在这里，我分享关于现代 Web 开发、技术框架学习记录以及极客生活的深度思考。","ShiGoldYao","我是一名全栈技术学习者，对构建高性能、可扩展的现代 Web 应用充满热情。过去一年里，我从初识互联网前后端开发，到逐步沉淀技术体系，始终保持着对前端、后端与工程化的持续探索。\n\n我坚信 “代码如诗”。除了日常学习与项目实践，我也会花大量时间关注开源社区，尝试摸索 WebAssembly、Rust 等前沿技术在浏览器端的更多可能，不断挑战性能与体验的边界。\n\n生活里的我并不只有代码：闲暇时会打打永劫无间，享受博弈与操作的快感；也喜欢打乒乓球，在运动中放松自己；当然，最幸福的时光，还是和女朋友一起慢慢生活、认真恋爱。","\u002F\u002F 🚀 开启学习之旅","","Vue , TypeScript , Nest , Mysql","成为优秀的前端全栈工程师","\u002F\u002F 欢迎来到我的技术世界","3","true","5",{"id":23,"title":24,"slug":25,"coverUrl":15,"summary":15,"content":26,"htmlContent":27,"categoryId":28,"viewCount":29,"likeCount":30,"isTop":31,"isPublish":30,"seoKeywords":15,"seoDescription":15,"publishTime":32,"createTime":33,"updateTime":34,"deleteTime":35,"category":36,"tags":42},"10","Axios 学习笔记","axios学习笔记","# Axios 学习笔记\n\n> 专为前端工程师设计的 Axios HTTP 客户端学习笔记\n\n---\n\n## 目录\n\n- [一、Axios 简介](#一axios-简介)\n- [二、安装与配置](#二安装与配置)\n- [三、基础用法](#三基础用法)\n- [四、请求配置](#四请求配置)\n- [五、响应结构](#五响应结构)\n- [六、并发请求](#六并发请求)\n- [七、拦截器](#七拦截器)\n- [八、错误处理](#八错误处理)\n- [九、实例创建](#九实例创建)\n- [十、取消请求](#十取消请求)\n- [十一、实战示例](#十一实战示例)\n- [十二、最佳实践](#十二最佳实践)\n- [十三、常见问题](#十三常见问题)\n- [十四、快速参考](#十四快速参考)\n\n---\n\n## 一、Axios 简介\n\n### 1.1 什么是 Axios\n\nAxios 是一个基于 Promise 的 HTTP 客户端，用于浏览器和 Node.js 环境。\n\n**特点：**\n- 支持 Promise API\n- 支持请求和响应拦截器\n- 支持请求数据和响应数据转换\n- 支持取消请求\n- 自动转换 JSON 数据\n- 客户端支持防御 XSRF\n\n### 1.2 为什么选择 Axios\n\n| 特性 | Axios | Fetch API |\n|------|-------|-----------|\n| Promise 支持 | ✅ | ✅ |\n| 拦截器 | ✅ | ❌ |\n| 自动 JSON 转换 | ✅ | ❌ |\n| 请求取消 | ✅ | ✅ |\n| 超时控制 | ✅ | ❌ |\n| 浏览器兼容性 | ✅ | IE 不支持 |\n| Node.js 支持 | ✅ | ✅ |\n\n### 1.3 与 Fetch API 对比\n\n```javascript\n\u002F\u002F Fetch API\nfetch('\u002Fapi\u002Fusers')\n  .then(response => response.json())\n  .then(data => console.log(data))\n  .catch(error => console.error(error));\n\n\u002F\u002F Axios\naxios.get('\u002Fapi\u002Fusers')\n  .then(response => console.log(response.data))\n  .catch(error => console.error(error));\n```\n\n---\n\n## 二、安装与配置\n\n### 2.1 安装\n\n```bash\n# 使用 npm\nnpm install axios\n\n# 使用 yarn\nyarn add axios\n\n# 使用 pnpm\npnpm add axios\n\n# 使用 CDN\n\u003Cscript src=\"https:\u002F\u002Fcdn.jsdelivr.net\u002Fnpm\u002Faxios\u002Fdist\u002Faxios.min.js\">\u003C\u002Fscript>\n```\n\n### 2.2 基本引入\n\n```javascript\n\u002F\u002F ES6 模块\nimport axios from 'axios';\n\n\u002F\u002F CommonJS\nconst axios = require('axios');\n\n\u002F\u002F CDN 方式\n\u002F\u002F 直接使用全局变量 axios\n```\n\n### 2.3 全局默认配置\n\n```javascript\n\u002F\u002F 设置默认 baseURL\naxios.defaults.baseURL = 'https:\u002F\u002Fapi.example.com';\n\n\u002F\u002F 设置默认请求头\naxios.defaults.headers.common['Authorization'] = 'Bearer token';\naxios.defaults.headers.post['Content-Type'] = 'application\u002Fjson';\n\n\u002F\u002F 设置超时时间（毫秒）\naxios.defaults.timeout = 5000;\n\n\u002F\u002F 设置响应数据类型\naxios.defaults.responseType = 'json';\n```\n\n---\n\n## 三、基础用法\n\n### 3.1 GET 请求\n\n```javascript\n\u002F\u002F 基本 GET 请求\naxios.get('\u002Fapi\u002Fusers')\n  .then(response => {\n    console.log(response.data);\n  })\n  .catch(error => {\n    console.error(error);\n  });\n\n\u002F\u002F 带参数的 GET 请求\naxios.get('\u002Fapi\u002Fusers', {\n  params: {\n    page: 1,\n    pageSize: 10\n  }\n})\n  .then(response => {\n    console.log(response.data);\n  });\n\n\u002F\u002F 使用 async\u002Fawait\nasync function getUsers getUsers() {\n  try {\n    const response = await axios.get('\u002Fapi\u002Fusers');\n    console.log(response.data);\n  } catch (error) {\n    console.error(error);\n  }\n}\n```\n\n### 3.2 POST 请求\n\n```javascript\n\u002F\u002F 基本 POST 请求\naxios.post('\u002Fapi\u002Fusers', {\n  name: '张三',\n  email: 'zhangsan@example.com'\n})\n  .then(response => {\n    console.log(response.data);\n  });\n\n\u002F\u002F 带配置的 POST 请求\naxios.post('\u002Fapi\u002Fusers', {\n  name: '李四',\n  email: 'lisi@example.com'\n}, {\n  headers: {\n    'Content-Type': 'application\u002Fjson'\n  }\n})\n  .then(response => {\n    console.log(response.data);\n  });\n\n\u002F\u002F 使用 async\u002Fawait\nasync function createUser createUser() {\n  try {\n    const response = await axios.post('\u002Fapi\u002Fusers', {\n      name: '王五',\n      email: 'wangwu@example.com'\n    });\n    console.log(response.data);\n  } catch (error) {\n    console.error(error);\n  }\n}\n```\n\n### 3.3 PUT 请求\n\n```javascript\n\u002F\u002F 更新用户\naxios.put('\u002Fapi\u002Fusers\u002F1', {\n  name: '张三更新',\n  email: 'zhangsan_new@example.com'\n})\n  .then(response => {\n    console.log(response.data);\n  });\n```\n\n### 3.4 DELETE 请求\n\n```javascript\n\u002F\u002F 删除用户\naxios.delete('\u002Fapi\u002Fusers\u002F1')\n  .then(response => {\n    console.log(response.data);\n  });\n```\n\n### 3.5 PATCH 请求\n\n```javascript\n\u002F\u002F 部分更新用户\naxios.patch('\u002Fapi\u002Fusers\u002F1', {\n  name: '张三更新'\n})\n  .then(response => {\n    console.log(response.data);\n  });\n```\n\n---\n\n## 四、请求配置\n\n### 4.1 完整配置选项\n\n```javascript\naxios({\n  method: 'get', \u002F\u002F 请求方法：get, post, put, delete, patch\n  url: '\u002Fapi\u002Fusers', \u002F\u002F 请求地址\n  baseURL: 'https:\u002F\u002Fapi.example.com', \u002F\u002F 基础 URL\n  \n  \u002F\u002F 请求头\n  headers: {\n    'Authorization': 'Bearer token',\n    'Content-Type': 'application\u002Fjson'\n  },\n  \n  \u002F\u002F 请求参数\n  params: {\n    page: 1,\n    pageSize: 10\n  },\n  \n  \u002F\u002F 请求体数据\n  data: {\n    name: '张三',\n    email: 'zhangsan@example.com'\n  },\n  \n  \u002F\u002F 超时时间（毫秒）\n  timeout: 5000,\n  \n  \u002F\u002F 响应数据类型：arraybuffer, blob, document, json, text, stream\n  responseType: 'json',\n  \n  \u002F\u002F 响应编码\n  responseEncoding: 'utf8',\n  \n  \u002F\u002F 跨域请求时是否携带凭证\n  withCredentials: false,\n  \n  \u002F\u002F 上传进度回调\n  onUploadProgress: function(progressEvent) {\n    const percentCompleted = Math.round(\n      (progressEvent.loaded * 100) \u002F progressEvent.total\n    );\n    console.log('上传进度:', percentCompleted + '%');\n  },\n  \n  \u002F\u002F 下载进度回调\n  onDownloadProgress: function(progressEvent) {\n    const percentCompleted = Math.round(\n      (progressEvent.loaded * 100) \u002F progressEvent.total\n    );\n    console.log('下载进度:', percentCompleted + '%');\n  },\n  \n  \u002F\u002F 请求体最大长度\n  maxContentLength: 2000,\n  \n  \u002F\u002F HTTP 响应体最大长度\n  maxBodyLength: 2000,\n  \n  \u002F\u002F 是否验证 SSL 证书\n  validateStatus: function(status) {\n    return status >= 200 && status \u003C 300;\n  }\n});\n```\n\n### 4.2 常用配置示例\n\n```javascript\n\u002F\u002F 带认证的请求\naxios.get('\u002Fapi\u002Fusers', {\n  headers: {\n    'Authorization': 'Bearer ' + localStorage.getItem('token')\n  }\n});\n\n\u002F\u002F 带超时的请求\naxios.get('\u002Fapi\u002Fusers', {\n  timeout: 3000\n});\n\n\u002F\u002F 上传文件\nconst formData = new FormData();\nformData.append('file', fileInput.files[0]);\n\naxios.post('\u002Fapi\u002Fupload', formData, {\n  headers: {\n    'Content-Type': 'multipart\u002Fform-data'\n  },\n  onUploadProgress: (progressEvent) => {\n    const progress = Math.round(\n      (progressEvent.loaded * 100) \u002F progressEvent.total\n    );\n    console.log('上传进度:', progress + '%');\n  }\n});\n\n\u002F\u002F 下载文件\naxios.get('\u002Fapi\u002Fdownload\u002Ffile.pdf', {\n  responseType: 'blob',\n  onDownloadProgress: (progressEvent) => {\n    const progress = Math.round(\n      (progressEvent.loaded * 100) \u002F progressEvent.total\n    );\n    console.log('下载进度:', progress + '%');\n  }\n})\n  .then(response => {\n    const url = window.URL.createObjectURL(new Blob([response.data]));\n    const link = document.createElement('a');\n    link.href = url;\n    link.setAttribute('download', 'file.pdf');\n    document.body.appendChild(link);\n    link.click();\n  });\n```\n\n---\n\n## 五、响应结构\n\n### 5.1 响应对象结构\n\n```javascript\naxios.get('\u002Fapi\u002Fusers')\n  .then(response => {\n    \u002F\u002F 响应数据\n    console.log(response.data);\n    \n    \u002F\u002F HTTP 状态码\n    console.log(response.status);\n    \n    \u002F\u002F HTTP 状态消息\n    console.log(response.statusText);\n    \n    \u002F\u002F 响应头\n    console.log(response.headers);\n    \n    \u002F\u002F 请求配置\n    console.log(response.config);\n    \n    \u002F\u002F 请求对象\n    console.log(response.request);\n  });\n```\n\n### 5.2 响应示例\n\n```javascript\n\u002F\u002F 成功响应\n{\n  data: {\n    id: 1,\n    name: '张三',\n    email: 'zhangsan@example.com'\n  },\n  status: 200,\n  statusText: 'OK',\n  headers: {\n    'content-type': 'application\u002Fjson',\n    'content-length': '123'\n  },\n  config: {\n    url: '\u002Fapi\u002Fusers\u002F1',\n    method: 'get',\n    headers: { ... }\n  },\n  request: XMLHttpRequest\n}\n\n\u002F\u002F 错误响应\n{\n  message: 'Request failed with status code 404',\n  name: 'Error',\n  code: 'ERR_BAD_REQUEST',\n  config: { ... },\n  request: XMLHttpRequest,\n  response: {\n    data: {\n      error: 'User not found'\n    },\n    status: 404,\n    statusText: 'Not Found',\n    headers: { ... }\n  }\n}\n```\n\n---\n\n## 六、并发请求\n\n### 6.1 使用 Promise.all\n\n```javascript\n\u002F\u002F 并发发送多个请求\nfunction getUserAndOrders getUserAndOrders(userId) {\n  const getUser = axios.get(`\u002Fapi\u002Fusers\u002F${userId}`);\n  const getOrders = axios.get(`\u002Fapi\u002Fusers\u002F${userId}\u002Forders`);\n  \n  Promise.all([getUser, getOrders])\n    .then(([userResponse, ordersResponse]) => {\n      console.log('用户信息:', userResponse.data);\n      console.log('订单信息:', ordersResponse.data);\n    })\n    .catch(error => {\n      console.error('请求失败:', error);\n    });\n}\n\n\u002F\u002F 使用 async\u002Fawait\nasync function getUserAndOrdersAsync(userId) {\n  try {\n    const [userResponse, ordersResponse] = await Promise.all([\n      axios.get(`\u002Fapi\u002Fusers\u002F${userId}`),\n      axios.get(`\u002Fapi\u002Fusers\u002F${userId}\u002Forders`)\n    ]);\n    \n    console.log('用户信息:', userResponse.data);\n    console.log('订单信息:', ordersResponse.data);\n  } catch (error) {\n    console.error('请求失败:', error);\n  }\n}\n```\n\n### 6.2 使用 axios.all\n\n```javascript\n\u002F\u002F axios.all 是 Promise.all 的别名\naxios.all([\n  axios.get('\u002Fapi\u002Fusers'),\n  axios.get('\u002Fapi\u002Forders'),\n  axios.get('\u002Fapi\u002Fproducts')\n])\n  .then(axios.spread((usersResponse, ordersResponse, productsResponse) => {\n    console.log('用户:', usersResponse.data);\n    console.log('订单:', ordersResponse.data);\n    console.log('产品:', productsResponse.data);\n  }));\n```\n\n### 6.3 并发请求的错误处理\n\n```javascript\n\u002F\u002F 处理部分失败的情况\nasync function fetchMultipleData() {\n  const requests = [\n    axios.get('\u002Fapi\u002Fusers').catch(e => ({ error: e, type: 'users' })),\n    axios.get('\u002Fapi\u002Forders').catch(e => ({ error: e, type: 'orders' })),\n    axios.get('\u002Fapi\u002Fproducts').catch(e => ({ error: e, type: 'products' }))\n  ];\n  \n  const results = await Promise.all(requests);\n  \n  results.forEach(result => {\n    if (result.error) {\n      console.error(`${result.type} 请求失败:`, result.error);\n    } else {\n      console.log(`${result.type} 数据:`, result.data);\n    }\n  });\n}\n```\n\n---\n\n## 七、拦截器\n\n### 7.1 请求拦截器\n\n```javascript\n\u002F\u002F 添加请求拦截器\naxios.interceptors.request.use(\n  config => {\n    \u002F\u002F 在发送请求之前做些什么\n    \n    \u002F\u002F 添加 token\n    const token = localStorage.getItem('token');\n    if (token) {\n      config.headers.Authorization = `Bearer ${token}`;\n    }\n    \n    \u002F\u002F 添加时间戳\n    config.params = {\n      ...config.params,\n      _t: Date.now()\n    };\n    \n    \u002F\u002F 显示加载动画\n    showLoading();\n    \n    console.log('请求配置:', config);\n    return config;\n  },\n  error => {\n    \u002F\u002F 对请求错误做些什么\n    console.error('请求错误:', error);\n    return Promise.reject(error);\n  }\n);\n```\n\n### 7.2 响应拦截器\n\n```javascript\n\u002F\u002F 添加响应拦截器\naxios.interceptors.response.use(\n  response => {\n    \u002F\u002F 对响应数据做点什么\n    \n    \u002F\u002F 隐藏加载动画\n    hideLoading();\n    \n    \u002F\u002F 统一处理响应数据\n    const { data, status } = response;\n    \n    if (status === 200) {\n      return data;\n    }\n    \n    return response;\n  },\n  error => {\n    \u002F\u002F 对响应错误做点什么\n    \n    \u002F\u002F 隐藏加载动画\n    hideLoading();\n    \n    \u002F\u002F 统一错误处理\n    if (error.response) {\n      const { status, data } = error.response;\n      \n      switch (status) {\n        case 401:\n          console.error('未授权，请登录');\n          \u002F\u002F 跳转到登录页\n          window.location.href = '\u002Flogin';\n          break;\n        case 403:\n          console.error('没有权限');\n          break;\n        case 404:\n          console.error('请求的资源不存在');\n          break;\n        case 500:\n          console.error('服务器错误');\n          break;\n        default:\n          console.error('请求错误:', data.message || '未知错误');\n      }\n    } else if (error.request) {\n      console.error('网络错误，请检查网络连接');\n    } else {\n      console.error('请求配置错误:', error.message);\n    }\n    \n    return Promise.reject(error);\n  }\n);\n```\n\n### 7.3 移除拦截器\n\n```javascript\n\u002F\u002F 保存拦截器引用\nconst requestInterceptor = axios.interceptors.request.use(config => {\n  console.log('请求拦截器');\n  return config;\n});\n\nconst responseInterceptor = axios.interceptors.response.use(response => {\n  console.log('响应拦截器');\n  return response;\n});\n\n\u002F\u002F 移除拦截器\naxios.interceptors.request.eject(requestInterceptor);\naxios.interceptors.response.eject(responseInterceptor);\n```\n\n### 7.4 完整拦截器示例\n\n```javascript\n\u002F\u002F utils\u002Frequest.js\nimport axios from 'axios';\nimport { message } from 'antd';\n\nconst service = axios.create({\n  baseURL: process.env.VUE_APP_BASE_API,\n  timeout: 10000\n});\n\nlet loadingCount = 0;\n\nfunction showLoading() {\n  if (loadingCount === 0) {\n    message.loading('加载中...', 0);\n  }\n  loadingCount++;\n}\n\nfunction hideLoading() {\n  loadingCount--;\n  if (loadingCount === 0) {\n    message.destroy();\n  }\n}\n\nservice.interceptors.request.use(\n  config => {\n    const token = localStorage.getItem('token');\n    if (token) {\n      config.headers.Authorization = `Bearer ${token}`;\n    }\n    \n    showLoading();\n    return config;\n  },\n  error => {\n    hideLoading();\n    return Promise.reject(error);\n  }\n);\n\nservice.interceptors.response.use(\n  response => {\n    hideLoading();\n    \n    const { code, data, message: msg } = response.data;\n    \n    if (code === 200) {\n      return data;\n    } else {\n      message.error(msg || '请求失败');\n      return Promise.reject(new Error(msg || '请求失败'));\n    }\n  },\n  error => {\n    hideLoading();\n    \n    if (error.response) {\n      const { status, data } = error.response;\n      \n      switch (status) {\n        case 401:\n          message.error('登录已过期，请重新登录');\n          localStorage.removeItem('token');\n          window.location.href = '\u002Flogin';\n          break;\n        case 403:\n          message.error('没有权限访问');\n          break;\n        case 404:\n          message.error('请求的资源不存在');\n          break;\n        case 500:\n          message.error('服务器错误');\n          break;\n        default:\n          message.error(data.message || '请求失败');\n      }\n    } else {\n      message.error('网络错误，请检查网络连接');\n    }\n    \n    return Promise.reject(error);\n  }\n);\n\nexport default service;\n```\n\n---\n\n## 八、错误处理\n\n### 8.1 错误类型\n\n```javascript\naxios.get('\u002Fapi\u002Fusers')\n  .catch(error => {\n    if (error.response) {\n      \u002F\u002F 服务器响应了，但状态码不在 2xx 范围内\n      console.log('响应数据:', error.response.data);\n      console.log('状态码:', error.response.status);\n      console.log('响应头:', error.response.headers);\n    } else if (error.request) {\n      \u002F\u002F 请求已发出，但没有收到响应\n      console.log('请求对象:', error.request);\n    } else {\n      \u002F\u002F 设置请求时出错\n      console.log('错误消息:', error.message);\n    }\n    \n    console.log('错误配置:', error.config);\n  });\n```\n\n### 8.2 统一错误处理\n\n```javascript\n\u002F\u002F 封装错误处理函数\nfunction handleError(error) {\n  if (!error) {\n    return '未知错误';\n  }\n  \n  if (error.response) {\n    const { status, data } = error.response;\n    \n    const errorMessages = {\n      400: '请求参数错误',\n      401: '未授权，请登录',\n      403: '没有权限访问',\n      404: '请求的资源不存在',\n      405: '请求方法不允许',\n      408: '请求超时',\n      500: '服务器内部错误',\n      502: '网关错误',\n      503: '服务不可用',\n      504: '网关超时'\n    };\n    \n    return data.message || errorMessages[status] || '请求失败';\n  } else if (error.request) {\n    return '网络错误，请检查网络连接';\n  } else {\n    return error.message || '请求配置错误';\n  }\n}\n\naxios.get('\u002Fapi\u002Fusers')\n  .catch(error => {\n    const errorMessage = handleError(error);\n    console.error(errorMessage);\n    alert(errorMessage);\n  });\n```\n\n### 8.3 重试机制\n\n```javascript\n\u002F\u002F 带重试的请求\nasync function axiosWithRetry(config, maxRetries = 3, delay = 1000) {\n  let retries = 0;\n  \n  while (retries \u003C maxRetries) {\n    try {\n      const response = await axios(config);\n      return response;\n    } catch (error) {\n      retries++;\n      \n      if (retries >= maxRetries) {\n        throw error;\n      }\n      \n      console.log(`请求失败，第 ${retries} 次重试...`);\n      await new Promise(resolve => setTimeout(resolve, delay));\n    }\n  }\n}\n\naxiosWithRetry({\n  method: 'get',\n  url: '\u002Fapi\u002Fusers'\n}, 3, 1000)\n  .then(response => {\n    console.log('请求成功:', response.data);\n  })\n  .catch(error => {\n    console.error('重试失败:', error);\n  });\n```\n\n---\n\n## 九、实例创建\n\n### 9.1 创建实例\n\n```javascript\n\u002F\u002F 创建自定义实例\nconst instance = axios.create({\n  baseURL: 'https:\u002F\u002Fapi.example.com',\n  timeout: 5000,\n  headers: {\n    'Content-Type': 'application\u002Fjson',\n    'Authorization': 'Bearer token'\n  }\n});\n\n\u002F\u002F 使用实例发送请求\ninstance.get('\u002Fusers')\n  .then(response => {\n    console.log(response.data);\n  });\n\ninstance.post('\u002Fusers', {\n  name: '张三'\n});\n```\n\n### 9.2 多实例示例\n\n```javascript\n\u002F\u002F 用户服务实例\nconst userService = axios.create({\n  baseURL: 'https:\u002F\u002Fapi.example.com\u002Fusers',\n  timeout: 5000\n});\n\n\u002F\u002F 订单服务实例\nconst orderService = axios.create({\n  baseURL: 'https:\u002F\u002Fapi.example.com\u002Forders',\n  timeout: 10000\n});\n\n\u002F\u002F 使用不同实例\nuserService.get('\u002Fprofile');\norderService.get('\u002Flist');\n```\n\n### 9.3 完整实例封装\n\n```javascript\n\u002F\u002F api\u002Fuser.js\nimport axios from 'axios';\n\nconst userApi = axios.create({\n  baseURL: 'https:\u002F\u002Fapi.example.com\u002Fapi\u002Fusers',\n  timeout: 5000\n});\n\nuserApi.interceptors.request.use(config => {\n  const token = localStorage.getItem('token');\n  if (token) {\n    config.headers.Authorization = `Bearer ${token}`;\n  }\n  return config;\n});\n\nexport default {\n  getUser(id) {\n    return userApi.get(`\u002F${id}`);\n  },\n  \n  getUsers(params) {\n    return userApi.get('\u002F', { params });\n  },\n  \n  createUser(data) {\n    return userApi.post('\u002F', data);\n  },\n  \n  updateUser(id, data) {\n    return userApi.put(`\u002F${id}`, data);\n  },\n  \n  deleteUser(id) {\n    return userApi.delete(`\u002F${id}`);\n  }\n};\n\n\u002F\u002F 使用\nimport userApi from '@\u002Fapi\u002Fuser';\n\nuserApi.getUser(1)\n  .then(user => {\n    console.log(user);\n  });\n```\n\n---\n\n## 十、取消请求\n\n### 10.1 使用 CancelToken\n\n```javascript\nconst CancelToken = axios.CancelToken;\nlet cancel;\n\naxios.get('\u002Fapi\u002Fusers', {\n  cancelToken: new CancelToken(function executor(c) {\n    cancel = c;\n  })\n});\n\n\u002F\u002F 取消请求\ncancel('请求被用户取消');\n```\n\n### 10.2 使用 AbortController\n\n```javascript\nconst controller = new AbortController();\n\naxios.get('\u002Fapi\u002Fusers', {\n  signal: controller.signal\n});\n\n\u002F\u002F 取消请求\ncontroller.abort();\n```\n\n### 10.3 实际应用场景\n\n```javascript\n\u002F\u002F 搜索框防抖 + 取消请求\nlet searchController = null;\n\nasync function searchUsers(keyword) {\n  \u002F\u002F 取消上一次请求\n  if (searchController) {\n    searchController.abort();\n  }\n  \n  searchController = new AbortController();\n  \n  try {\n    const response = await axios.get('\u002Fapi\u002Fusers', {\n      params: { keyword },\n      signal: searchController.signal\n    });\n    \n    return response.data;\n  } catch (error) {\n    if (axios.isCancel(error)) {\n      console.log('请求被取消:', error.message);\n    } else {\n      console.error('搜索失败:', error);\n    }\n  }\n}\n\n\u002F\u002F 页面卸载时取消请求\nuseEffect(() => {\n  const controller = new AbortController();\n  \n  fetchData(controller.signal);\n  \n  return () => {\n    controller.abort();\n  };\n}, []);\n```\n\n---\n\n## 十一、实战示例\n\n### 11.1 用户管理系统\n\n```javascript\n\u002F\u002F api\u002Fuser.js\nimport request from '@\u002Futils\u002Frequest';\n\nexport default {\n  login(username, password) {\n    return request.post('\u002Fapi\u002Fauth\u002Flogin', {\n      username,\n      password\n    });\n  },\n  \n  register(data) {\n    return request.post('\u002Fapi\u002Fauth\u002Fregister', data);\n  },\n  \n  logout() {\n    return request.post('\u002Fapi\u002Fauth\u002Flogout');\n  },\n  \n  getUserInfo() {\n    return request.get('\u002Fapi\u002Fuser\u002Finfo');\n  },\n  \n  updateUserInfo(data) {\n    return request.put('\u002Fapi\u002Fuser\u002Finfo', data);\n  },\n  \n  changePassword(oldPassword, newPassword) {\n    return request.post('\u002Fapi\u002Fuser\u002Fchange-password', {\n      oldPassword,\n      newPassword\n    });\n  },\n  \n  uploadAvatar(file) {\n    const formData = new FormData();\n    formData.append('avatar', file);\n    \n    return request.post('\u002Fapi\u002Fuser\u002Favatar', formData, {\n      headers: {\n        'Content-Type': 'multipart\u002Fform-data'\n      }\n    });\n  }\n};\n\n\u002F\u002F React 组件中使用\nimport React, { useState } from 'react';\nimport userApi from '@\u002Fapi\u002Fuser';\n\nfunction LoginForm() {\n  const [username, setUsername] = useState('');\n  const [password, setPassword] = useState('');\n  const [loading, setLoading] = useState(false);\n  \n  const handleLogin = async (e) => {\n    e.preventDefault();\n    setLoading(true);\n    \n    try {\n      const { token, userInfo } = await userApi.login(username, password);\n      \n      localStorage.setItem('token', token);\n      localStorage.setItem('userInfo', JSON.stringify(userInfo));\n      \n      alert('登录成功');\n      window.location.href = '\u002Fdashboard';\n    } catch (error) {\n      console.error('登录失败:', error);\n    } finally {\n      setLoading(false);\n    }\n  };\n  \n  return (\n    \u003Cform onSubmit={handleLogin}>\n      \u003Cinput\n        type=\"text\"\n        value={username}\n        onChange={(e) => setUsername(e.target.value)}\n        placeholder=\"用户名\"\n      \u002F>\n      \u003Cinput\n        type=\"password\"\n        value={password}\n        onChange={(e) => setPassword(e.target.value)}\n        placeholder=\"密码\"\n      \u002F>\n      \u003Cbutton type=\"submit\" disabled={loading}>\n        {loading ? '登录中...' : '登录'}\n      \u003C\u002Fbutton>\n    \u003C\u002Fform>\n  );\n}\n```\n\n### 11.2 博客系统\n\n```javascript\n\u002F\u002F api\u002Farticle.js\nimport request from '@\u002Futils\u002Frequest';\n\nexport default {\n  getArticles(params) {\n    return request.get('\u002Fapi\u002Farticles', { params });\n  },\n  \n  getArticle(id) {\n    return request.get(`\u002Fapi\u002Farticles\u002F${id}`);\n  },\n  \n  createArticle(data) {\n    return request.post('\u002Fapi\u002Farticles', data);\n  },\n  \n  updateArticle(id, data) {\n    return request.put(`\u002Fapi\u002Farticles\u002F${id}`, data);\n  },\n  \n  deleteArticle(id) {\n    return request.delete(`\u002Fapi\u002Farticles\u002F${id}`);\n  },\n  \n  likeArticle(id) {\n    return request.post(`\u002Fapi\u002Farticles\u002F${id}\u002Flike`);\n  },\n  \n  getComments(articleId, params) {\n    return request.get(`\u002Fapi\u002Farticles\u002F${articleId}\u002Fcomments`, { params });\n  },\n  \n  createComment(articleId, content) {\n    return request.post(`\u002Fapi\u002Farticles\u002F${articleId}\u002Fcomments`, {\n      content\n    });\n  }\n};\n\n\u002F\u002F Vue 组件中使用\nimport { ref, onMounted } from 'vue';\nimport articleApi from '@\u002Fapi\u002Farticle';\n\nexport default {\n  setup() {\n    const articles = ref([]);\n    const loading = ref(false);\n    const pagination = ref({\n      page: 1,\n      pageSize: 10,\n      total: 0\n    });\n    \n    const fetchArticles = async () => {\n      loading.value = true;\n      \n      try {\n        const { list, total } = await articleApi.getArticles({\n          page: pagination.value.page,\n          pageSize: pagination.value.pageSize\n        });\n        \n        articles.value = list;\n        pagination.value.total = total;\n      } catch (error) {\n        console.error('获取文章列表失败:', error);\n      } finally {\n        loading.value = false;\n      }\n    };\n    \n    const handlePageChange = (page) => {\n      pagination.value.page = page;\n      fetchArticles();\n    };\n    \n    onMounted(() => {\n      fetchArticles();\n    });\n    \n    return {\n      articles,\n      loading,\n      pagination,\n      handlePageChange\n    };\n  }\n};\n```\n\n### 11.3 电商系统\n\n```javascript\n\u002F\u002F api\u002Fproduct.js\nimport request from '@\u002Futils\u002Frequest';\n\nexport default {\n  getProducts(params) {\n    return request.get('\u002Fapi\u002Fproducts', { params });\n  },\n  \n  getProduct(id) {\n    return request.get(`\u002Fapi\u002Fproducts\u002F${id}`);\n  },\n  \n  searchProducts(keyword, params) {\n    return request.get('\u002Fapi\u002Fproducts\u002Fsearch', {\n      params: { keyword, ...params }\n    });\n  }\n};\n\n\u002F\u002F api\u002Fcart.js\nexport default {\n  getCart() {\n    return request.get('\u002Fapi\u002Fcart');\n  },\n  \n  addToCart(productId, quantity) {\n    return request.post('\u002Fapi\u002Fcart\u002Fitems', {\n      productId,\n      quantity\n    });\n  },\n  \n  updateCartItem(itemId, quantity) {\n    return request.put(`\u002Fapi\u002Fcart\u002Fitems\u002F${itemId}`, {\n      quantity\n    });\n  },\n  \n  removeFromCart(itemId) {\n    return request.delete(`\u002Fapi\u002Fcart\u002Fitems\u002F${itemId}`);\n  },\n  \n  clearCart() {\n    return request.delete('\u002Fapi\u002Fcart');\n  }\n};\n\n\u002F\u002F api\u002Forder.js\nexport default {\n  createOrder(data) {\n    return request.post('\u002Fapi\u002Forders', data);\n  },\n  \n  getOrders(params) {\n    return request.get('\u002Fapi\u002Forders', { params });\n  },\n  \n  getOrder(id) {\n    return request.get(`\u002Fapi\u002Forders\u002F${id}`);\n  },\n  \n  cancelOrder(id) {\n    return request.post(`\u002Fapi\u002Forders\u002F${id}\u002Fcancel`);\n  },\n  \n  payOrder(id, paymentMethod) {\n    return request.post(`\u002Fapi\u002Forders\u002F${id}\u002Fpay`, {\n      paymentMethod\n    });\n  }\n};\n\n\u002F\u002F 购物车组件\nimport React, { useState, useEffect } from 'react';\nimport cartApi from '@\u002Fapi\u002Fcart';\n\nfunction ShoppingCart() {\n  const [cartItems, setCartItems] = useState([]);\n  const [loading, setLoading] = useState(false);\n  \n  const fetchCart = async () => {\n    setLoading(true);\n    \n    try {\n      const items = await cartApi.getCart();\n      setCartItems(items);\n    } catch (error) {\n      console.error('获取购物车失败:', error);\n    } finally {\n      setLoading(false);\n    }\n  };\n  \n  const addToCart = async (productId, quantity = 1) => {\n    try {\n      await cartApi.addToCart(productId, quantity);\n      await fetchCart();\n      alert('添加到购物车成功');\n    } catch (error) {\n      console.error('添加到购物车失败:', error);\n    }\n  };\n  \n  const updateQuantity = async (itemId, quantity) => {\n    try {\n      await cartApi.updateCartItem(itemId, quantity);\n      await fetchCart();\n    } catch (error) {\n      console.error('更新数量失败:', error);\n    }\n  };\n  \n  const removeFromCart = async (itemId) => {\n    try {\n      await cartApi.removeFromCart(itemId);\n      await fetchCart();\n    } catch (error) {\n      console.error('删除失败:', error);\n    }\n  };\n  \n  useEffect(() => {\n    fetchCart();\n  }, []);\n  \n  return (\n    \u003Cdiv>\n      \u003Ch2>购物车\u003C\u002Fh2>\n      {loading ? (\n        \u003Cp>加载中...\u003C\u002Fp>\n      ) : (\n        \u003Cul>\n          {cartItems.map(item => (\n            \u003Cli key={item.id}>\n              \u003Cspan>{item.productName}\u003C\u002Fspan>\n              \u003Cspan>¥{item.price}\u003C\u002Fspan>\n              \u003Cinput\n                type=\"number\"\n                value={item.quantity}\n                onChange={(e) => updateQuantity(item.id, parseInt(e.target.value))}\n              \u002F>\n              \u003Cbutton onClick={() => removeFromCart(item.id)}>删除\u003C\u002Fbutton>\n            \u003C\u002Fli>\n          ))}\n        \u003C\u002Ful>\n      )}\n    \u003C\u002Fdiv>\n  );\n}\n```\n\n### 11.4 文件上传\n\n```javascript\n\u002F\u002F api\u002Fupload.js\nimport request from '@\u002Futils\u002Frequest';\n\nexport default {\n  uploadFile(file, onProgress) {\n    const formData = new FormData();\n    formData.append('file', file);\n    \n    return request.post('\u002Fapi\u002Fupload', formData, {\n      headers: {\n        'Content-Type': 'multipart\u002Fform-data'\n      },\n      onUploadProgress: (progressEvent) => {\n        const progress = Math.round(\n          (progressEvent.loaded * 100) \u002F progressEvent.total\n        );\n        if (onProgress) {\n          onProgress(progress);\n        }\n      }\n    });\n  },\n  \n  uploadMultipleFiles(files, onProgress) {\n    const formData = new FormData();\n    files.forEach((file, index) => {\n      formData.append(`files[${index}]`, file);\n    });\n    \n    return request.post('\u002Fapi\u002Fupload\u002Fmultiple', formData, {\n      headers: {\n        'Content-Type': 'multipart\u002Fform-data'\n      },\n      onUploadProgress: (progressEvent) => {\n        const progress = Math.round(\n          (progressEvent.loaded * 100) \u002F progressEvent.total\n        );\n        if (onProgress) {\n          onProgress(progress);\n        }\n      }\n    });\n  }\n};\n\n\u002F\u002F 文件上传组件\nimport React, { useState } from 'react';\nimport uploadApi from '@\u002Fapi\u002Fupload';\n\nfunction FileUpload() {\n  const [file, setFile] = useState(null);\n  const [uploading, setUploading] = useState(false);\n  const [progress, setProgress] = useState(0);\n  \n  const handleFileChange = (e) => {\n    setFile(e.target.files[0]);\n  };\n  \n  const handleUpload = async () => {\n    if (!file) {\n      alert('请选择文件');\n      return;\n    }\n    \n    setUploading(true);\n    setProgress(0);\n    \n    try {\n      const result = await uploadApi.uploadFile(file, (progress) => {\n        setProgress(progress);\n      });\n      \n      alert('上传成功');\n      console.log('上传结果:', result);\n    } catch (error) {\n      console.error('上传失败:', error);\n      alert('上传失败');\n    } finally {\n      setUploading(false);\n    }\n  };\n  \n  return (\n    \u003Cdiv>\n      \u003Cinput type=\"file\" onChange={handleFileChange} \u002F>\n      \u003Cbutton onClick={handleUpload} disabled={uploading}>\n        {uploading ? `上传中 ${progress}%` : '上传'}\n      \u003C\u002Fbutton>\n      {uploading && (\n        \u003Cdiv>\n          \u003Cdiv>上传进度: {progress}%\u003C\u002Fdiv>\n          \u003Cprogress value={progress} max={100} \u002F>\n        \u003C\u002Fdiv>\n      )}\n    \u003C\u002Fdiv>\n  );\n}\n```\n\n---\n\n## 十二、最佳实践\n\n### 12.1 统一 API 封装\n\n```javascript\n\u002F\u002F utils\u002Frequest.js\nimport axios from 'axios';\nimport { message } from 'antd';\n\nconst service = axios.create({\n  baseURL: process.env.REACT_APP_BASE_API,\n  timeout: 10000\n});\n\nservice.interceptors.request.use(\n  config => {\n    const token = localStorage.getItem('token');\n    if (token) {\n      config.headers.Authorization = `Bearer ${token}`;\n    }\n    return config;\n  },\n  error => {\n    return Promise.reject(error);\n  }\n);\n\nservice.interceptors.response.use(\n  response => {\n    const { code, data, message: msg } = response.data;\n    \n    if (code === 200) {\n      return data;\n    } else {\n      message.error(msg || '请求失败');\n      return Promise.reject(new Error(msg || '请求失败'));\n    }\n  },\n  error => {\n    if (error.response?.status === 401) {\n      localStorage.removeItem('token');\n      window.location.href = '\u002Flogin';\n    }\n    message.error(error.message || '请求失败');\n    return Promise.reject(error);\n  }\n);\n\nexport default service;\n\n\u002F\u002F api\u002Findex.js\nimport request from '@\u002Futils\u002Frequest';\n\nexport default {\n  user: {\n    login(data) {\n      return request.post('\u002Fauth\u002Flogin', data);\n    },\n    getInfo() {\n      return request.get('\u002Fuser\u002Finfo');\n    }\n  },\n  article: {\n    getList(params) {\n      return request.get('\u002Farticles', { params });\n    },\n    getDetail(id) {\n      return request.get(`\u002Farticles\u002F${id}`);\n    }\n  }\n};\n```\n\n### 12.2 环境配置\n\n```javascript\n\u002F\u002F .env.development\nREACT_APP_BASE_API=http:\u002F\u002Flocalhost:3000\u002Fapi\n\n\u002F\u002F .env.production\nREACT_APP_BASE_API=https:\u002F\u002Fapi.example.com\n\n\u002F\u002F config.js\nconst config = {\n  development: {\n    baseURL: 'http:\u002F\u002Flocalhost:3000\u002Fapi',\n    timeout: 10000\n  },\n  production: {\n    baseURL: 'https:\u002F\u002Fapi.example.com',\n    timeout: 5000\n  }\n};\n\nexport default config[process.env.NODE_ENV];\n```\n\n### 12.3 TypeScript 支持\n\n```typescript\n\u002F\u002F types\u002Fapi.ts\nexport interface User {\n  id: number;\n  username: string;\n  email: string;\n  avatar?: string;\n}\n\nexport interface Article {\n  id: number;\n  title: string;\n  content: string;\n  author: User;\n  createdAt: string;\n}\n\nexport interface ApiResponse\u003CT> {\n  code: number;\n  data: T;\n  message: string;\n}\n\n\u002F\u002F api\u002Fuser.ts\nimport request from '@\u002Futils\u002Frequest';\nimport type { User, ApiResponse } from '@\u002Ftypes\u002Fapi';\n\nexport const getUserInfo = (): Promise\u003CApiResponse\u003CUser>> => {\n  return request.get('\u002Fuser\u002Finfo');\n};\n\nexport const updateUser = (\n  data: Partial\u003CUser>\n): Promise\u003CApiResponse\u003CUser>> => {\n  return request.put('\u002Fuser\u002Finfo', data);\n};\n```\n\n### 12.4 请求缓存\n\n```javascript\n\u002F\u002F utils\u002Fcache.js\nconst cache = new Map();\n\nexport function withCache(key, fn, ttl = 60000) {\n  const cached = cache.get(key);\n  \n  if (cached && Date.now() - cached.timestamp \u003C ttl) {\n    return Promise.resolve(cached.data);\n  }\n  \n  return fn().then(data => {\n    cache.set(key, {\n      data,\n      timestamp: Date.now()\n    });\n    return data;\n  });\n}\n\nexport function clearCache(key) {\n  if (key) {\n    cache.delete(key);\n  } else {\n    cache.clear();\n  }\n}\n\n\u002F\u002F 使用\nimport { withCache } from '@\u002Futils\u002Fcache';\n\nfunction getUserInfo() {\n  return withCache('userInfo', () => {\n    return axios.get('\u002Fapi\u002Fuser\u002Finfo');\n  });\n}\n```\n\n### 12.5 请求防抖\n\n```javascript\n\u002F\u002F utils\u002Fdebounce.js\nlet debounceTimer = null;\n\nexport function debounceRequest(fn, delay = 300) {\n  return new Promise((resolve, reject) => {\n    if (debounceTimer) {\n      clearTimeout(debounceTimer);\n    }\n    \n    debounceTimer = setTimeout(async () => {\n      try {\n        const result = await fn();\n        resolve(result);\n      } catch (error) {\n        reject(error);\n      }\n    }, delay);\n  });\n}\n\n\u002F\u002F 使用\nimport { debounceRequest } from '@\u002Futils\u002Fdebounce';\n\nfunction searchUsers(keyword) {\n  return debounceRequest(() => {\n    return axios.get('\u002Fapi\u002Fusers', { params: { keyword } });\n  });\n}\n```\n\n---\n\n## 十三、常见问题\n\n### 13.1 跨域问题\n\n**解决方案 1：配置代理（开发环境）**\n\n```javascript\n\u002F\u002F package.json\n{\n  \"proxy\": \"http:\u002F\u002Flocalhost:3000\"\n}\n\n\u002F\u002F 或使用 http-proxy-middleware\n\u002F\u002F src\u002FsetupProxy.js\nconst { createProxyMiddleware } = require('http-proxy-middleware');\n\nmodule.exports = function(app) {\n  app.use(\n    '\u002Fapi',\n    createProxyMiddleware({\n      target: 'http:\u002F\u002Flocalhost:3000',\n      changeOrigin: true\n    })\n  );\n};\n```\n\n**解决方案 2：CORS（生产环境）**\n\n```javascript\n\u002F\u002F 后端配置 CORS（Node.js + Express）\nconst express = require('express');\nconst cors = require('cors');\n\nconst app = express();\n\napp.use(cors({\n  origin: 'http:\u002F\u002Flocalhost:8080',\n  credentials: true\n}));\n```\n\n### 13.2 请求超时\n\n```javascript\n\u002F\u002F 设置超时时间\naxios.get('\u002Fapi\u002Fusers', {\n  timeout: 5000\n});\n\n\u002F\u002F 全局设置\naxios.defaults.timeout = 5000;\n\n\u002F\u002F 实例设置\nconst instance = axios.create({\n  timeout: 5000\n});\n```\n\n### 13.3 大文件上传\n\n```javascript\n\u002F\u002F 分片上传\nasync function uploadLargeFile(file, chunkSize = 1024 * 1024) {\n  const chunks = Math.ceil(file.size \u002F chunkSize);\n  const results = [];\n  \n  for (let i = 0; i \u003C chunks; i++) {\n    const start = i * chunkSize;\n    const end = Math.min(start + chunkSize, file.size);\n    const chunk = file.slice(start, end);\n    \n    const formData = new FormData();\n    formData.append('file', chunk);\n    formData.append('chunkIndex', i);\n    formData.append('totalChunks', chunks);\n    formData.append('fileName', file.name);\n    \n    const result = await axios.post('\u002Fapi\u002Fupload\u002Fchunk', formData);\n    results.push(result.data);\n  }\n  \n  return results;\n}\n```\n\n### 13.4 并发请求限制\n\n```javascript\n\u002F\u002F 限制并发请求数量\nclass RequestQueue {\n  constructor(maxConcurrent = 5) {\n    this.maxConcurrent = maxConcurrent;\n    this.queue = [];\n    this.running = 0;\n  }\n  \n  add(request) {\n    return new Promise((resolve, reject) => {\n      this.queue.push({\n        request,\n        resolve,\n        reject\n      });\n      this.run();\n    });\n  }\n  \n  async run() {\n    if (this.running >= this.maxConcurrent || this.queue.length === 0) {\n      return;\n    }\n    \n    this.running++;\n    const { request, resolve, reject } = this.queue.shift();\n    \n    try {\n      const result = await request();\n      resolve(result);\n    } catch (error) {\n      reject(error);\n    } finally {\n      this.running--;\n      this.run();\n    }\n  }\n}\n\nconst queue = new RequestQueue(3);\n\nqueue.add(() => axios.get('\u002Fapi\u002Fusers\u002F1'));\nqueue.add(() => axios.get('\u002Fapi\u002Fusers\u002F2'));\nqueue.add(() => axios.get('\u002Fapi\u002Fusers\u002F3'));\n```\n\n---\n\n## 十四、快速参考\n\n### 14.1 常用方法\n\n```javascript\n\u002F\u002F GET 请求\naxios.get(url[, config])\n\n\u002F\u002F POST 请求\naxios.post(url[, data[, config]])\n\n\u002F\u002F PUT 请求\naxios.put(url[, data[, config]])\n\n\u002F\u002F DELETE 请求\naxios.delete(url[, config])\n\n\u002F\u002F PATCH 请求\naxios.patch(url[, data[, config]])\n\n\u002F\u002F 通用请求\naxios(config)\n```\n\n### 14.2 常用配置\n\n```javascript\n{\n  baseURL: 'https:\u002F\u002Fapi.example.com',\n  timeout: 5000,\n  headers: {\n    'Authorization': 'Bearer token',\n    'Content-Type': 'application\u002Fjson'\n  },\n  params: {},\n  data: {},\n  responseType: 'json',\n  withCredentials: false\n}\n```\n\n### 14.3 响应结构\n\n```javascript\n{\n  data: {},\n  status: 200,\n  statusText: 'OK',\n  headers: {},\n  config: {},\n  request: {}\n}\n```\n\n### 14.4 错误处理\n\n```javascript\naxios.get('\u002Fapi\u002Fusers')\n  .catch(error => {\n    if (error.response) {\n      \u002F\u002F 服务器响应了，但状态码不在 2xx 范围内\n    } else if (error.request) {\n      \u002F\u002F 请求已发出，但没有收到响应\n    } else {\n      \u002F\u002F 设置请求时出错\n    }\n  });\n```\n\n---\n\n**祝学习愉快！掌握 Axios，轻松处理 HTTP 请求！** 🚀\n",null,"1",33,1,0,"2026-04-07T16:15:56.021Z","2026-04-07T16:15:56.024Z","2026-05-26T01:39:34.275Z","0",{"id":28,"categoryName":37,"slug":38,"description":39,"sort":31,"isEnable":30,"createTime":40,"updateTime":41,"deleteTime":31},"前端开发","frontend-engineering","2222","2026-04-03T02:36:11.945Z","2026-04-07T16:38:46.496Z",[],[44],{"id":45,"articleId":46,"parentId":31,"nickname":47,"email":48,"content":39,"avatar":15,"website":15,"ipAddress":49,"userAgent":50,"isApproved":30,"createTime":51,"updateTime":51,"deleteTime":31},2,10,"22","yaoxingjin88@gmail.com","::1","Mozilla\u002F5.0 (Windows NT 10.0; Win64; x64) AppleWebKit\u002F537.36 (KHTML, like Gecko) Chrome\u002F147.0.0.0 Safari\u002F537.36","2026-04-22T12:58:59.539Z",[]]