重置AbortController值:React+Axios下载场景的边缘问题
解决AbortController复用导致重复终止请求的问题
之前用useRef保存AbortController的方案能应对常规场景,但在下载弹窗的场景下存在问题:用户点击下载打开进度模态框,关闭弹窗时终止请求,但再次点击下载时,新请求会直接被终止——因为组件没重新渲染,ref里的AbortController实例还是之前被abort过的,对应的signal处于终止状态。
原问题代码
AbortController ref定义
let controller = useRef(new AbortController()).current;
关闭模态框终止请求函数
const closeModal = () => { // 关闭模态框逻辑 controller.abort() }
下载请求函数
const downloadFile = async (type) => { // 一些逻辑 const res = await axios({ url: "https://www.something.com", onDownloadProgress: (progressEvent) => { // 进度计算逻辑 }, signal: controller.signal }) }
修复方案
核心思路是每次发起下载请求时,重新创建AbortController实例,替换ref中的旧实例,确保每次请求用的都是未被终止的新signal。
修改后的代码
AbortController ref定义
const controllerRef = useRef(new AbortController());
关闭模态框终止请求函数
const closeModal = () => { // 关闭模态框逻辑 controllerRef.current.abort(); }
下载请求函数(关键修改)
const downloadFile = async (type) => { // 每次发起请求前,重置为新的AbortController实例 controllerRef.current = new AbortController(); // 一些逻辑 try { const res = await axios({ url: "https://www.something.com", onDownloadProgress: (progressEvent) => { // 进度计算逻辑 }, signal: controllerRef.current.signal }); // 请求成功后的处理逻辑 } catch (error) { // 捕获请求取消的错误,避免控制台报错 if (axios.isCancel(error)) { console.log("下载已取消"); } else { // 处理其他下载错误 console.error("下载失败", error); } } }
这样修改后,每次点击下载都会生成新的AbortController,之前的终止操作不会影响到新请求,完美解决重复终止的问题。
内容的提问来源于stack exchange,提问作者labs
相关产品推荐
相关产品推荐

