多API调用场景下如何正确控制页面加载器的显隐?
问题描述
我创建了一个状态变量:
let [isLoading, setIsLoading] = useState(false)
需要调用三个API,对应的函数如下:
const api1 = ()=>{ setIsLoading(true) callApi() setIsLoading(false) } const api2 = ()=>{ setIsLoading(true) callApi() setIsLoading(false) } const api3 = ()=>{ setIsLoading(true) callApi() setIsLoading(false) }
我在useEffect()中调用这三个函数,使用axios发起API请求。当前问题是任意一个API调用成功后,就会执行setIsLoading(false),导致加载器提前停止,而此时另外两个API尚未完成。
我需要实现加载器在所有API调用完成后才停止,UI中通过isLoading && <Loader />渲染加载器。
我知道一种解决方案是创建三个状态变量,通过(isLoading1 || isLoading2 || isLoading3) && <Loader />来控制,但不想创建多个状态,请问有没有更好的处理加载动画的方式?
解决方案
方案1:使用Promise.all()统一管理请求
只保留单个isLoading状态,将所有API请求包装为Promise,通过Promise.all()等待全部请求完成后再关闭加载状态,适合需要同时发起所有请求的场景。
修改后的代码示例:
const fetchAllData = async () => { setIsLoading(true); try { // 传入所有API请求的Promise(axios请求本身返回Promise) await Promise.all([ callApi(), // 对应原api1的请求逻辑 callApi(), // 对应原api2的请求逻辑 callApi() // 对应原api3的请求逻辑 ]); } catch (error) { // 统一处理请求错误 console.error('API请求失败:', error); } finally { // 无论成功或失败,最终关闭加载状态 setIsLoading(false); } }; // 在useEffect中触发统一请求 useEffect(() => { fetchAllData(); }, []);
注意事项:
Promise.all()会在任意一个请求失败时立即进入catch块;如果允许部分请求失败,可替换为Promise.allSettled(),它会等待所有请求完成(无论成败)后再执行后续逻辑。- 确保每个
callApi返回的是Promise,axios的请求默认满足此要求。
方案2:用计数器跟踪请求进度
如果需要灵活控制API的调用时机(非同时发起),可以用计数器记录未完成的请求数,仅当计数器归0时才关闭加载状态,同时保留单个isLoading变量。
代码示例:
const [isLoading, setIsLoading] = useState(false); const [pendingCount, setPendingCount] = useState(0); // 封装通用请求处理函数 const handleApiCall = async (apiFn) => { setPendingCount(prev => prev + 1); // 首次请求时开启加载 if (!isLoading) setIsLoading(true); try { await apiFn(); } catch (error) { console.error('请求出错:', error); } finally { setPendingCount(prev => { const newCount = prev - 1; // 所有请求完成后关闭加载 if (newCount === 0) setIsLoading(false); return newCount; }); } }; // 重写原API调用函数 const api1 = () => handleApiCall(callApi); const api2 = () => handleApiCall(callApi); const api3 = () => handleApiCall(callApi); // 在useEffect中调用三个API useEffect(() => { api1(); api2(); api3(); }, []);
这个方案支持分批调用API的场景,比如用户操作触发单个API时,也能准确维护加载状态,无需新增多个isLoading变量。
内容的提问来源于stack exchange,提问作者Varun Deva
相关产品推荐
相关产品推荐

