axios 基本操作

axios 基本操作


一、axios 概述

axios 是一个基于 Promise 的 HTTP 客户端库,用于浏览器和 Node.js 环境中发送网络请求。与原生 XMLHttpRequestfetch 相比,axios 提供了更简洁的 API 和更强的功能。

核心优势:

  • Promise 风格 :基于 Promise,支持 async/await 语法,避免回调地狱。
  • 自动转换 JSON :响应数据自动由 JSON 字符串转为 JavaScript 对象,无需手动调用 JSON.parse()
  • 拦截器:可在请求发出前或响应到达后统一处理(如添加 token、统一报错)。
  • 取消请求 :通过 AbortController 取消不再需要的请求。
  • 超时控制 :内置 timeout 参数,超过指定时间自动中断请求。
  • 跨平台 :浏览器端基于 XMLHttpRequest,Node.js 端基于 http 模块,两套环境使用同一套 API。

二、安装与引入

安装

bash 复制代码
# npm 项目中安装
npm install axios
html 复制代码
<!-- 通过 CDN 直接引入(浏览器环境) -->
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>

引入

js 复制代码
// ES Module 方式(推荐,用于现代前端项目)
import axios from 'axios';

// CommonJS 方式(Node.js 环境)
const axios = require('axios');

引入 CDN 后,axios 会挂载为全局变量,可直接使用,无需额外配置。


三、基本请求方法

axios 支持所有 HTTP 方法,最常用的是 getpostputdelete

GET 请求

js 复制代码
// 方式一:简写
async function getUsers() {
  const response = await axios.get('https://api.example.com/users');
  console.log(response.data);
}

// 方式二:完整写法(通过 config 对象指定 method)
async function getUsers2() {
  const response = await axios({
    method: 'get',
    url: 'https://api.example.com/users',
  });
  console.log(response.data);
}

携带查询参数:

js 复制代码
// 直接拼接在 URL 中
axios.get('https://api.example.com/users?id=1&status=active');

// 通过 params 参数传入(推荐,axios 会自动拼接到 URL 末尾)
axios.get('https://api.example.com/users', {
  params: {
    id: 1,
    status: 'active',
  },
});
// 实际请求地址:https://api.example.com/users?id=1&status=active

使用 params 对象的方式更清晰,也便于动态修改参数。

POST 请求

POST 用于向服务器提交数据(创建资源),数据放在请求体中。

js 复制代码
// 方式一:简写
async function createUser() {
  const response = await axios.post('https://api.example.com/users', {
    name: '张三',
    email: 'zhangsan@example.com',
    age: 25,
  });
  console.log('创建成功', response.data);
}

// 方式二:完整写法
async function createUser2() {
  const response = await axios({
    method: 'post',
    url: 'https://api.example.com/users',
    data: {
      name: '张三',
      email: 'zhangsan@example.com',
      age: 25,
    },
  });
  console.log('创建成功', response.data);
}

要点:

  • GET 请求的参数用 params,放在 URL 中。
  • POST / PUT / PATCH 请求的参数用 data,放在请求体中。

PUT 请求

PUT 用于整体更新已有资源。

js 复制代码
async function updateUser() {
  const response = await axios.put('https://api.example.com/users/1', {
    name: '张三(更新)',
    email: 'zhangsan_new@example.com',
    age: 26,
  });
  console.log('更新成功', response.data);
}

DELETE 请求

DELETE 用于删除资源。

js 复制代码
async function deleteUser() {
  const response = await axios.delete('https://api.example.com/users/1');
  console.log('删除成功');
}

请求方法对照

方法 用途 传参方式 对应简写
GET 获取数据 URL 查询参数 params axios.get()
POST 创建资源 请求体 data axios.post()
PUT 整体更新资源 请求体 data axios.put()
PATCH 局部更新资源 请求体 data axios.patch()
DELETE 删除资源 URL 路径参数 axios.delete()

四、请求配置

除了 methodurl,axios 支持丰富的配置项来定制请求行为。

常用请求头

js 复制代码
axios.get('https://api.example.com/data', {
  headers: {
    'Authorization': 'Bearer your_token_here',
    'Content-Type': 'application/json',
    'X-Custom-Header': 'custom-value',
  },
});

超时设置

js 复制代码
axios.get('https://api.example.com/data', {
  timeout: 5000,  // 单位:毫秒,超过 5 秒未响应则中断并抛出错误
});

发送不同格式的数据

js 复制代码
// JSON 格式(默认,Content-Type 自动设为 application/json)
axios.post('/api/data', {
  key: 'value',
});

// 表单格式(Content-Type: application/x-www-form-urlencoded)
const params = new URLSearchParams();
params.append('username', 'admin');
params.append('password', '123456');
axios.post('/api/login', params);

// 文件上传(Content-Type: multipart/form-data)
const formData = new FormData();
formData.append('file', fileInput.files[0]);
formData.append('description', '头像图片');
axios.post('/api/upload', formData);

五、响应结构

axios 的响应对象包含以下字段:

js 复制代码
async function inspectResponse() {
  const response = await axios.get('https://api.example.com/users/1');

  console.log(response.data);        // 服务端返回的响应体数据(已被解析为对象)
  console.log(response.status);      // HTTP 状态码,如 200、404、500
  console.log(response.statusText);  // HTTP 状态文本,如 "OK"、"Not Found"
  console.log(response.headers);     // 响应头,为对象格式
  console.log(response.config);      // 本次请求所使用的配置对象
}
字段 类型 说明
data any 响应体数据,自动根据 Content-Type 解析
status number HTTP 状态码(200、201、404、500 等)
statusText string 状态码对应的文本描述
headers object 响应头键值对
config object 当前请求的完整配置
request object 发起此次请求的底层对象(浏览器中为 XMLHttpRequest)

实际使用中,response.data 是最常用的字段。


六、错误处理

axios 对 HTTP 状态码不在 2xx 范围内的响应均视为错误,会进入 catch 分支。

基本错误捕获

js 复制代码
async function fetchWithErrorHandling() {
  try {
    const response = await axios.get('https://api.example.com/users/999');
    console.log('成功', response.data);
  } catch (error) {
    // 推荐写法:先判断 error.response 是否存在
    if (error.response) {
      // 服务端返回了响应,但状态码不在 2xx 范围
      console.log('状态码:', error.response.status);    // 如 404
      console.log('响应数据:', error.response.data);     // 服务端返回的错误信息
    } else if (error.request) {
      // 请求已经发出但未收到响应(网络不通、超时等)
      console.log('网络错误或无响应');
    } else {
      // 请求在发送前就出错了(如配置错误)
      console.log('请求配置错误', error.message);
    }
  }
}

三类错误对应的场景:

错误类型 触发条件 判断方式
服务端错误 服务端返回了 4xx / 5xx 状态码 error.response 存在
网络错误 请求已发出但未收到响应 error.request 存在但 error.response 不存在
配置错误 请求配置有误,未能发出 error.request 也不存在

async/await 中的错误处理

js 复制代码
async function fetchUser(id) {
  try {
    const response = await axios.get(`https://api.example.com/users/${id}`);
    console.log(response.data);
  } catch (error) {
    if (error.response) {
      // 服务端返回了错误状态码
      const status = error.response.status;
      if (status === 404) {
        console.error('用户不存在');
      } else if (status === 500) {
        console.error('服务器内部错误');
      }
    } else {
      console.error('网络异常', error.message);
    }
  }
}

根据状态码统一处理

js 复制代码
async function requestWithStatusHandling() {
  try {
    const response = await axios.get('/api/data');
    console.log(response.data);
  } catch (error) {
    if (!error.response) return;

    switch (error.response.status) {
      case 400:
        console.error('请求参数有误');
        break;
      case 401:
        console.error('未登录或登录已过期');
        // 可在此跳转到登录页
        break;
      case 403:
        console.error('没有访问权限');
        break;
      case 404:
        console.error('请求的资源不存在');
        break;
      case 500:
        console.error('服务器内部错误');
        break;
      default:
        console.error(`未知错误,状态码:${error.response.status}`);
    }
  }
}

七、拦截器

拦截器是 axios 最强大的特性之一,允许在请求发送前或响应到达 try/catch 处理逻辑前统一拦截。

请求拦截器

在请求发出前执行,常用于统一添加 token、设置 loading。

js 复制代码
// 添加请求拦截器
axios.interceptors.request.use(
  config => {
    // 在发送请求前做些什么:例如从 localStorage 读取 token 并附加到请求头
    const token = localStorage.getItem('token');
    if (token) {
      config.headers.Authorization = `Bearer ${token}`;
    }
    console.log('请求发出:', config.method.toUpperCase(), config.url);
    return config;  // 必须返回 config,否则请求会被阻塞
  },
  error => {
    // 请求错误时的处理
    return Promise.reject(error);
  }
);

响应拦截器

在响应数据到达 await 调用处或 catch 分支之前执行,常用于统一处理错误提示、刷新 token。

js 复制代码
// 添加响应拦截器
axios.interceptors.response.use(
  response => {
    // 对 2xx 范围内的响应做统一处理
    // 例如:只返回 data,让调用方不用每次都写 .data
    return response.data;
  },
  error => {
    // 对超出 2xx 范围的响应做统一处理
    if (error.response) {
      const status = error.response.status;
      if (status === 401) {
        // token 过期,清除本地信息并跳转登录页
        localStorage.removeItem('token');
        window.location.href = '/login';
      }
      // 统一弹出错误提示
      console.error(error.response.data.message || '请求失败');
    }
    return Promise.reject(error);
  }
);

取消拦截器

js 复制代码
const myInterceptor = axios.interceptors.request.use(config => {
  // ...
  return config;
});

// 在不需要时移除该拦截器
axios.interceptors.request.eject(myInterceptor);

八、实例与默认配置

当项目中需要访问多个不同域名的后端服务,或不同模块需要不同的超时时间时,可以创建独立的 axios 实例,避免污染全局默认配置。

创建实例

js 复制代码
// 创建一个带默认配置的 axios 实例
const apiClient = axios.create({
  baseURL: 'https://api.example.com',  // 基础 URL,后续请求只需写路径
  timeout: 10000,                       // 默认超时 10 秒
  headers: {
    'Content-Type': 'application/json',
  },
});

// 使用实例发送请求,URL 会自动拼接 baseURL
apiClient.get('/users');            // 实际请求 https://api.example.com/users
apiClient.post('/users', { name: '李四' });
apiClient.put('/users/1', { name: '李四(更新)' });
apiClient.delete('/users/1');

多实例场景示例

js 复制代码
// 业务 API
const businessAPI = axios.create({
  baseURL: 'https://api.example.com/v1',
  timeout: 5000,
});

// 文件上传服务(时间更长)
const uploadAPI = axios.create({
  baseURL: 'https://upload.example.com',
  timeout: 30000,  // 上传给 30 秒
});

// 第三方 API
const thirdPartyAPI = axios.create({
  baseURL: 'https://third-party-api.com',
  timeout: 8000,
});

每个实例有独立的拦截器,互不干扰:

js 复制代码
// 给业务 API 实例添加拦截器
businessAPI.interceptors.request.use(config => {
  config.headers.Authorization = `Bearer ${getToken()}`;
  return config;
});

// 上传实例不需要 token,不加该拦截器

修改全局默认配置

js 复制代码
// 修改全局 axios 的默认配置
axios.defaults.baseURL = 'https://api.example.com';
axios.defaults.timeout = 5000;
axios.defaults.headers.common['Authorization'] = 'Bearer token_value';
axios.defaults.headers.post['Content-Type'] = 'application/json';

推荐使用实例而非修改全局默认值,避免不同模块的配置互相影响。


九、取消请求

在某些场景下(如用户快速切换页面、输入框防抖搜索),需要取消尚未完成的请求以节省资源。

js 复制代码
// 创建 AbortController,在外面定义以便随时调用 abort()
const controller = new AbortController();

async function fetchWithCancel() {
  try {
    const response = await axios.get('https://api.example.com/search?q=abc', {
      signal: controller.signal,  // 传入 signal
    });
    console.log(response.data);
  } catch (error) {
    if (axios.isCancel(error)) {
      console.log('请求已被取消', error.message);
    } else {
      console.error('请求出错', error);
    }
  }
}

// 发起请求(不 await,让它在后台执行)
fetchWithCancel();

// 在需要时取消请求(例如用户点击取消按钮时调用)
controller.abort();

搜索防抖示例:每次用户输入时取消上一个未完成的搜索请求。

js 复制代码
let controller = null;

searchInput.addEventListener('input', async (e) => {
  // 取消上一次未完成的请求
  if (controller) {
    controller.abort();
  }

  // 新建 controller
  controller = new AbortController();

  try {
    const response = await axios.get('/api/search', {
      params: { keyword: e.target.value },
      signal: controller.signal,
    });
    renderResults(response.data);
  } catch (error) {
    if (!axios.isCancel(error)) {
      console.error('搜索失败', error);
    }
  }
});

十、并发请求

当需要同时发送多个请求并等待全部完成后一起处理时,可使用 Promise.all

js 复制代码
async function loadDashboard() {
  try {
    const [usersRes, postsRes, statsRes] = await Promise.all([
      axios.get('/api/users'),
      axios.get('/api/posts'),
      axios.get('/api/stats'),
    ]);

    console.log('用户:', usersRes.data);
    console.log('文章:', postsRes.data);
    console.log('统计:', statsRes.data);
  } catch (error) {
    // 任意一个请求失败,Promise.all 都会进入 catch
    console.error('加载失败:', error);
  }
}

axios.allaxios.spread 也可用于并发请求,但它们只是 Promise.all 和数组解构的封装,上述写法更简洁直白。

要点:Promise.all 中任一请求失败都会导致整体进入 catch。如果希望部分失败时仍能获取成功的结果,可使用 Promise.allSettled()

相关推荐
不一样的少年_1 小时前
Claude Code 是怎么自己改代码的?答案藏在这 4 个工具里
前端·agent·ai编程
问商十三载2 小时前
RAG的适用边界在哪里?2026年价值与局限详解
大数据·前端·人工智能
爱勇宝3 小时前
人生没有最好的年龄,只有最好的状态
前端
幼儿园技术家3 小时前
前端 Node 全家桶
前端·js or ts
无人生还3 小时前
从 Vue3 到 React · 快速上手系列第 9 篇:自定义 Hook(对标 Composables)
前端·vue.js·react.js
张龙6873 小时前
RAG 知识库问答系统实战:分块、混合检索、RRF 融合与重排全链路拆解
前端
用户1306095607233 小时前
第二章学完后,我对 webpack5 前端工程化的一点理解
前端
a1117763 小时前
小鸡下蛋 小游戏 html
前端·开源·html
码哥DFS3 小时前
算法练习day1-备战2027届秋招
前端·javascript·数据结构·算法