axios的两种异步方式对比

发布于:2025-09-08 ⋅ 阅读:(16) ⋅ 点赞:(0)

这两种方式本质上都是异步的,都是基于 Promise 的机制,但它们在语法风格、可读性、错误处理、控制流方面有一些关键区别。下面我来帮你全面对比:

语法结构对比

方式 写法 特点
.then().catch() axios.get(...).then(...).catch(...) 链式调用,适合简单逻辑
async/await await axios.get(...) 更接近同步语法,适合复杂流程

示例对比

方式一:.then().catch()(链式调用)

axios.get('/api/data')
  .then(res => {
    console.log(res.data);
  })
  .catch(err => {
    console.error(err);
  });
  • 优点:语法简洁,适合快速调用。

  • 缺点:嵌套多层 .then() 时容易变得混乱(回调地狱)。

方式二:async/await(同步风格)

async function fetchData() {
  try {
    const res = await axios.get('/api/data');
    console.log(res.data);
  } catch (err) {
    console.error(err);
  }
}
  • 优点:逻辑清晰,异常处理统一,适合复杂流程。

  • 缺点:必须在 async 函数中使用,略微多一层结构。

错误处理对比

场景 .then().catch() async/await
单个请求失败 .catch() 捕获 try/catch 捕获
多个请求嵌套 多个 .catch() 一个 try/catch 统一处理
异步函数中抛错 不易追踪 更易定位错误位置

控制流对比(多个请求)

.then() 写法:

axios.get('/api/user')
  .then(user => {
    return axios.get(`/api/posts?user=${user.id}`);
  })
  .then(posts => {
    console.log(posts.data);
  })
  .catch(err => console.error(err));

async/await 写法:

async function getUserPosts() {
  try {
    const user = await axios.get('/api/user');
    const posts = await axios.get(`/api/posts?user=${user.data.id}`);
    console.log(posts.data);
  } catch (err) {
    console.error(err);
  }
}

async/await 更像同步代码,逻辑更清晰,调试更容易。

总结建议

使用场景 推荐方式
简单请求 .then().catch()
多步异步流程 async/await
错误处理统一 async/await
可读性优先 async/await
快速测试或临时调用 .then()

如果你正在开发 Vue 项目中的 API 模块,我建议你封装所有请求为 async 函数,这样在组件中调用时更清晰、更易维护。

企业级 API 请求模块示例

基于 axios,支持以下功能:

  • ✅ 自动注入 Token(如 JWT)

  • ✅ 全局错误处理(如 401、500)

  • ✅ 请求/响应拦截器

  • ✅ Loading 状态支持

  • ✅ 自动重试机制(可选)

  • ✅ 支持异步 async/await 调用

项目结构建议

src/
├── api/
│   ├── axios.js         # axios 实例配置
│   ├── request.js       # 封装请求方法
│   └── modules/
│       └── user.js      # 用户相关接口

1.axios.js — 创建 axios 实例

// src/api/axios.js
import axios from 'axios';

const instance = axios.create({
  baseURL: '/api', // 可根据环境配置
  timeout: 10000,
  headers: {
    'Content-Type': 'application/json'
  }
});

// 请求拦截器
instance.interceptors.request.use(config => {
  const token = localStorage.getItem('access_token');
  if (token) {
    config.headers.Authorization = `Bearer ${token}`;
  }
  return config;
}, error => Promise.reject(error));

// 响应拦截器
instance.interceptors.response.use(response => {
  return response.data;
}, error => {
  const { response } = error;
  if (response) {
    if (response.status === 401) {
      console.warn('未授权,请重新登录');
      // 可跳转登录页或清除 token
    } else if (response.status >= 500) {
      console.error('服务器错误');
    }
  } else {
    console.error('网络异常');
  }
  return Promise.reject(error);
});

export default instance;

2.request.js — 封装请求方法

// src/api/request.js
import axios from './axios';

export const get = (url, params = {}) => {
  return axios.get(url, { params });
};

export const post = (url, data = {}) => {
  return axios.post(url, data);
};

export const put = (url, data = {}) => {
  return axios.put(url, data);
};

export const del = (url, params = {}) => {
  return axios.delete(url, { params });
};

3. modules/user.js — 用户接口模块

// src/api/modules/user.js
import { get, post } from '../request';

export const login = data => post('/login', data);
export const getUserInfo = () => get('/user/info');
export const logout = () => post('/logout');

4. Vue 中调用示例

import { login, getUserInfo } from '@/api/modules/user';

async function handleLogin(formData) {
  try {
    const res = await login(formData);
    localStorage.setItem('access_token', res.access_token);
    console.log('登录成功:', res.user);
  } catch (err) {
    console.error('登录失败:', err);
  }
}

可选增强功能

功能 实现方式
自动刷新 Token 拦截器中检测 401,调用 refresh 接口
Loading 状态 在请求前后触发全局 loading(如 Vuex 或 Pinia)
请求重试 使用 axios-retry 插件或自定义逻辑
多环境配置 使用 .env 文件设置 baseURL

网站公告

今日签到

点亮在社区的每一天
去签到