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

相关推荐
Hygge-star4 分钟前
Flask音频处理:构建高效的Web音频应用指南
前端·flask·音视频·pygame·csdn开发云
江城开朗的豌豆15 分钟前
JavaScript篇:回调地狱退散!6年老前端教你写出优雅异步代码
前端·javascript·面试
飞鸟malred27 分钟前
vite+tailwind封装组件库
前端·react.js·npm
Angindem28 分钟前
从零搭建uniapp项目
前端·vue.js·uni-app
java干货35 分钟前
深度解析:Spring Boot 配置加载顺序、优先级与 bootstrap 上下文
前端·spring boot·bootstrap
Uyker1 小时前
微信小程序动态效果实战指南:从悬浮云朵到丝滑列表加载
前端·微信小程序·小程序
小小小小宇1 小时前
前端按需引入总结
前端
小小小小宇2 小时前
React 的 DOM diff笔记
前端
小小小小宇2 小时前
react和vue DOM diff 简单对比
前端
我在北京coding2 小时前
6套bootstrap后台管理界面源码
前端·bootstrap·html