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

相关推荐
子兮曰4 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰4 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万4 天前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝4 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
三十而立洋4 天前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
卡布鲁4 天前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
汉堡大王95274 天前
Jev:不是聊天机器人, 而是一个智能 if 语句
前端·人工智能·后端
梦想很大很大4 天前
从运行事实到回归证据:Workrun 的 Telemetry 与 Evaluation 实践
前端·人工智能·后端
计算机魔术师4 天前
Meta Muse agent 接入 Shopify 的 Shop Pay 实现代理式购物
前端
沙蒿同学4 天前
我用 Go 搭了一条 AI Agent 流水线:从 1 张商品图到一整套淘宝详情页
前端·javascript·后端