异步函数(API调用)顺序执行失败问题排查
顺序API调用异常问题分析与解决
问题现象
需要依次执行两个API调用:
- 先发送POST请求创建新游戏,获取返回的
code值 - 再用这个
code发送GET请求获取对应游戏数据
但实际运行出现异常:
- POST请求返回的
code是ST231,但finally中打印的code状态为空 - GET请求返回的却是
code为BX892的游戏数据,并非刚创建的游戏
原因分析
- React状态更新的异步性:
setNewCode是异步操作,调用后不会立刻更新code变量。finally中打印的是当前闭包捕获的初始code值(空字符串),而非刚设置的新值。 - 闭包捕获旧值:
useEffect的依赖数组为空,意味着asyncFunction只会在组件首次渲染时执行,它捕获的是组件初始化时的code状态(空字符串)。此时发送GET请求时,拼接的路径是/games/(空code),API可能返回了默认数据或之前创建的游戏数据(比如BX892)。
解决方法
不需要通过React状态传递API调用的中间值,直接将POST返回的code存到普通变量中,用于后续GET请求:
const dateTime = new Date().toJSON(); const [code, setNewCode] = useState(""); const [gameData, setGameData] = useState<any>([]); useEffect(() => { const asyncFunction = async () => { try { // 发送POST请求并获取返回的code const postResponse = await axios.post(apiUrl + "/games", { game: { name: dateTime, }, }); const gameCode = postResponse.data.code; console.log(gameCode); // 此处打印ST231 setNewCode(gameCode); // 若需渲染该code,再更新状态 // 用普通变量gameCode发送GET请求 const getResponse = await axios.get(apiUrl + "/games/" + gameCode); console.log(JSON.stringify(getResponse.data)); setGameData(getResponse.data); // 直接存储原始数据,无需转字符串 console.log("Get is done"); } catch (error) { console.error(error); } }; asyncFunction(); }, []);
额外优化点
- 避免混合使用
await和.then/.catch,统一用async/await写法,代码更简洁易读 gameData的类型定义为any[],但返回的是单个游戏对象,建议修正类型为any或具体的游戏类型- 不要将
getResponse.data转成字符串后存入状态,直接存原始对象更便于后续使用
内容的提问来源于stack exchange,提问作者TTOVARISCHH
相关产品推荐
相关产品推荐

