React Native中如何通过useEffect顺序执行异步API请求
问题核心原因
你现在的代码有两个典型问题导致顺序不生效:
- 两个异步函数在useEffect里并列调用,没有等待前一个执行完成就会启动下一个,本身就存在竞态
- 就算你给
getUserToken()加await,React的state更新是异步批处理的,getUserId函数闭包里捕获的永远是组件初始化时的空userToken值,哪怕setUserToken已经触发,getUserId也拿不到最新值 - 额外提一句:你写的
AsyncStorage.getItem("userToken", userToken)传参错误,这个API只需要传入存储key作为第一个参数,第二个参数是多余的。
推荐实现方式
不要靠state在两个独立函数之间传递中间值,把强依赖的串行步骤放到同一个异步流程里执行,从根源上避开闭包陷阱,同时保证执行顺序,代码如下:
useEffect(() => { const initPageData = async () => { try { // 第一步:读取本地存储的token const storedToken = await AsyncStorage.getItem("userToken"); if (!storedToken) { // 无token场景可在这里处理,比如跳登录页 console.log("未检测到登录凭证"); return; } // 如果页面其他逻辑需要用到token,再存到state setUserToken(storedToken); // 第二步:携带刚拿到的token请求用户信息 const userRes = await xano.get("/auth/me", { headers: { Authorization: storedToken }, }); const uid = userRes.data.id; setUserId(uid); // 注意:setState是异步的,不要在setUserId之后立刻console.log(userId),直接打局部变量uid即可 console.log("当前用户ID:", uid); } catch (err) { console.log("页面初始化数据加载失败", err); // 可在这里统一处理错误,比如token过期清空存储跳登录 } }; initPageData(); }, []);
方案说明
- 所有初始化逻辑封装在同一个async函数内,通过await严格保证执行顺序:token读取完成前绝对不会发起用户信息请求
- 请求用户信息时直接使用await拿到的局部变量
storedToken,完全不依赖state更新,彻底解决闭包拿到旧值的问题 - 增加了空token提前判断,避免发起无效的鉴权请求
- 错误统一在流程内捕获,不需要在多个拆分函数里重复写错误处理逻辑,维护性更好
- useEffect依赖数组为空,整个逻辑只会在组件首次挂载时执行一次,完全符合你的需求
如果你确实需要拆分两个函数做逻辑复用,记得让读取token的函数返回拿到的token值,请求用户信息的函数接收token作为入参,不要直接读取闭包内的state变量,调用时按顺序await即可,参考写法:
const getUserToken = async () => { try { const token = await AsyncStorage.getItem("userToken"); setUserToken(token); return token; } catch (err) { console.log("读取token失败", err); return null; } }; const getUserId = async (token) => { if (!token) return; try { const res = await xano.get("/auth/me", { headers: { Authorization: token }, }); setUserId(res.data.id); } catch (err) { console.log("获取用户信息失败", err); } }; useEffect(() => { const runInit = async () => { const token = await getUserToken(); await getUserId(token); }; runInit(); }, []);
内容的提问来源于stack exchange,提问作者bolsen26
相关产品推荐
相关产品推荐

