Axios 进阶指南:掌握请求取消与进度监控的艺术

一、请求取消:防止不必要的网络流量

当用户快速切换页面或重复触发请求时,未完成的请求会造成资源浪费。Axios 提供了两种取消机制:

1. 传统方案:CancelToken (适用于 v0.22.0 之前)

javascript 复制代码
import axios from 'axios';

// 创建取消令牌源
const source = axios.CancelToken.source();

axios.get('/api/data', {
  cancelToken: source.token
}).catch(thrown => {
  if (axios.isCancel(thrown)) {
    console.log('请求已取消', thrown.message);
  }
});

// 取消请求(可传递原因)
source.cancel('用户导航离开页面');

2. 现代方案:AbortController (推荐)

go 复制代码
const controller = new AbortController();

axios.get('/api/data', {
  signal: controller.signal
}).catch(error => {
  if (axios.isCancel(error)) {
    console.log('取消原因:', error.message);
  }
});

// 取消请求
controller.abort('操作被用户终止');

最佳实践场景:

  • 页面切换时取消未完成请求
  • 表单提交防重复点击
  • 搜索框输入防抖处理
  • 组件卸载时清理请求

二、进度监控:提升用户体验的关键

大文件传输场景中,进度反馈至关重要。Axios 通过 onUploadProgress 和 onDownloadProgress 提供实时进度更新:

上传进度监控

ini 复制代码
const uploadFile = (file) => {
  const formData = new FormData();
  formData.append('file', file);

  axios.post('/upload', formData, {
    headers: { 'Content-Type': 'multipart/form-data' },
    onUploadProgress: progressEvent => {
      const percentCompleted = Math.round(
        (progressEvent.loaded * 100) / progressEvent.total
      );
      console.log(`上传进度: ${percentCompleted}%`);
      
      // 更新UI进度条
      progressBar.value = percentCompleted;
    }
  }).then(response => {
    console.log('上传完成!');
  });
};

下载进度监控

ini 复制代码
axios.get('/large-file', {
  responseType: 'blob',
  onDownloadProgress: progressEvent => {
    const percentCompleted = Math.round(
      (progressEvent.loaded * 100) / progressEvent.total
    );
    console.log(`下载进度: ${percentCompleted}%`);
    
    // 显示下载进度通知
    showNotification(`下载中... ${percentCompleted}%`);
  }
}).then(response => {
  // 创建文件下载链接
  const url = URL.createObjectURL(response.data);
  const a = document.createElement('a');
  a.href = url;
  a.download = 'file.zip';
  document.body.appendChild(a);
  a.click();
});

高级技巧:

ini 复制代码
// 创建可复用的进度监控Hook
const useProgress = () => {
  const [progress, setProgress] = useState(0);

  const progressHandler = useCallback(progressEvent => {
    const percent = Math.round(
      (progressEvent.loaded * 100) / progressEvent.total
    );
    setProgress(percent);
  }, []);

  return [progress, progressHandler];
};

// 在组件中使用
const [uploadProgress, onUploadProgress] = useProgress();

三、实战应用:结合取消与进度功能

scss 复制代码
// 创建可取消的带进度监控请求
const fetchDataWithProgress = () => {
  const controller = new AbortController();
  
  axios.get('/api/large-data', {
    signal: controller.signal,
    onDownloadProgress: progressEvent => {
      const percent = Math.round(
        (progressEvent.loaded * 100) / progressEvent.total
      );
      updateProgressBar(percent);
    }
  }).then(processData).catch(handleError);
  
  // 返回取消方法
  return () => controller.abort();
};

// 组件中使用
useEffect(() => {
  const cancelRequest = fetchDataWithProgress();
  
  return () => {
    // 组件卸载时取消请求
    cancelRequest(); 
  };
}, []);

四、注意事项与优化建议

  1. 精度问题:

    • progressEvent.total 可能不可用(返回0)
    • 添加安全检查:const total = progressEvent.total || 1;
  2. 性能优化:

    javascript 复制代码
    // 使用节流避免频繁渲染
    onDownloadProgress: throttle(progressEvent => {
      // 更新逻辑
    }, 200)
  3. 错误处理:

    go 复制代码
    .catch(error => {
      if (axios.isCancel(error)) {
        // 取消请求的特殊处理
      } else {
        // 常规错误处理
      }
    })
  4. 服务端支持:

    • 确保服务器正确设置 Content-Length 头
    • 分块传输编码可能影响进度准确性

结语

通过合理运用 Axios 的取消和进度监控功能,您可以显著提升应用性能与用户体验。关键要点:

  1. 使用 AbortController 管理现代取消逻辑
  2. onUploadProgress/onDownloadProgress 实现精细进度控制
  3. 结合 React/Vue 生命周期实现自动请求清理
  4. 大文件传输时提供可视化反馈

这些高级技巧将使您的应用在网络请求处理方面更加专业和高效,特别是在处理大文件传输和复杂用户交互场景时表现尤为突出。

拓展阅读:尝试将这些功能与 Axios 拦截器结合,创建全局请求管理解决方案,进一步提升代码复用性和可维护性。

相关推荐
裕晟资质规划2 分钟前
三类涉密资质延续时限差异分析:军工60日与集成印制3个月的边界
java·服务器·前端·网络·安全
ShineWinsu10 分钟前
对于JavaScript:JavaScript基础语法的解析
开发语言·前端·javascript·面试·web·基础语法·循环
月夏18 分钟前
Vue3 转 React:18 项对照表 + 5 个必踩的坑(附 7 天上手路线)
前端
广州华水科技26 分钟前
单北斗GNSS位移监测系统的应用与维护解析
前端
梦曦i1 小时前
uni-storage 0.1.0 发布:TTL过期管理+多实例隔离
前端·storage·uni-app x
猫头_2 小时前
AI 流式传输工程指南:模型吐出半截 JSON,前端如何边收边渲染?
前端·javascript·llm
console.log('npc')2 小时前
第 1 章 项目概述与环境搭建
前端·人工智能·大模型
定栓2 小时前
Webpack迁到Vite第七节(二):全家桶移除 — Babel 全家桶深度分析
前端·webpack·node.js
IT_陈寒3 小时前
React组件莫名重渲染?你可能忘了这个小细节
前端·人工智能·后端
鶴哥只手遮天3 小时前
React 19.3.1 源码深度剖析-第 12 章(下)RSC 与 Flight 协议
前端·react.js·开源