如何在API调用时终止等待并退出函数,避免后续导航执行?
解决异步更新后意外导航的问题
核心思路
你遇到的问题本质是异步请求未被终止,且请求完成后未校验当前页面/用户状态,导致后续导航逻辑错误执行。以下是几种直接有效的解决方案:
1. 使用AbortController取消Axios请求
现代浏览器原生支持AbortController,Axios 0.22.0及以上版本可通过该API终止请求,让Promise直接进入catch分支,避免后续代码执行。
// 声明控制器变量,可放在组件状态或模块作用域中 let abortController = null; async function update() { abortController = new AbortController(); try { const res = await axios.post('update', { data: '123' }, { signal: abortController.signal // 将信号绑定到请求 }); navigate(previousScreen); } catch (error) { // 单独处理请求取消的情况 if (axios.isCancel(error)) { console.log('请求已被终止'); return; } // 处理其他业务错误 } finally { abortController = null; } } // 在页面跳转、登出等操作时调用,终止请求 function handleLogoutOrNavigate() { if (abortController) { abortController.abort('页面跳转/登出,终止异步请求'); } // 执行登出或导航逻辑 }
2. 校验页面/组件活跃状态
如果不需要终止请求,可在执行导航前检查当前页面是否为发起请求的页面,或组件是否仍处于挂载状态(以React为例):
import { useRef, useEffect } from 'react'; // 用ref跟踪组件挂载状态 const isMounted = useRef(true); useEffect(() => { return () => { isMounted.current = false; }; }, []); async function update() { try { const res = await axios.post('update', { data: '123' }); // 仅在组件活跃时执行导航 if (isMounted.current) { navigate(previousScreen); } } catch (error) { // 处理错误 } }
3. 全局管理请求队列
如果存在多个异步操作需要统一终止,可维护一个全局请求控制器集合,在登出时批量终止所有请求:
const activeRequests = new Set(); async function update() { const controller = new AbortController(); activeRequests.add(controller); try { const res = await axios.post('update', { data: '123' }, { signal: controller.signal }); navigate(previousScreen); } catch (error) { if (axios.isCancel(error)) return; // 处理错误 } finally { activeRequests.delete(controller); } } // 登出时终止所有活跃请求 function handleLogout() { activeRequests.forEach(controller => { controller.abort('登出操作,终止所有异步请求'); }); activeRequests.clear(); // 执行登出逻辑 }
内容的提问来源于stack exchange,提问作者Siva Karthick Rajan K
相关产品推荐
相关产品推荐

