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 通过 onUploadProgressonDownloadProgress 提供实时进度更新:

上传进度监控

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 拦截器结合,创建全局请求管理解决方案,进一步提升代码复用性和可维护性。

相关推荐
若梦plus26 分钟前
React之react-dom中的dom-server与dom-client
前端·react.js
若梦plus28 分钟前
react-router-dom中的几种路由详解
前端·react.js
若梦plus28 分钟前
Vue服务端渲染
前端·vue.js
Mr...Gan39 分钟前
VUE3(四)、组件通信
前端·javascript·vue.js
OEC小胖胖41 分钟前
渲染篇(二):解密Diff算法:如何用“最少的操作”更新UI
前端·算法·ui·状态模式·web
万少1 小时前
AI编程神器!Trae+Claude4.0 简单配置 让HarmonyOS开发效率飙升 - 坚果派
前端·aigc·harmonyos
前端工作日常1 小时前
我学习到的描述项目持续迭代具体成果
前端·测试
德育处主任1 小时前
p5.js 从零开始创建 3D 模型,createModel入门指南
前端·数据可视化·canvas
前端工作日常1 小时前
我学习到的 npx 命令
前端·npm
你的人类朋友1 小时前
❤️‍🔥BFF架构版的hello world
前端·后端·架构