Node.js/Express中异步函数内Await未等待问题求助
解决英雄联盟玩家数据查询页面提前加载的问题
嘿,我完全懂你现在的困扰——做英雄联盟玩家数据对比网站时,页面总是抢在数据获取完成前就加载出来,试了async函数和Promise却越弄越懵,这种时序问题确实容易绕进去!
先给你捋清楚核心问题:页面渲染逻辑没有等待异步数据请求完成就执行了,导致渲染时拿到的是空数据或者未resolved的Promise,自然显示不对。下面我结合你提到的核心函数,一步步给你修正方案:
第一步:把核心函数改成标准的async/await格式
你的getSummonerID这类数据请求函数,必须改成async函数,并且用await等待fetch的结果,同时做好错误处理:
async function getSummonerID(summonerRegion, summonerName) { try { // 等待fetch请求完成,拿到响应 const response = await fetch(`https://${summonerRegion}.api.riotgames.com/lol/summoner/v4/summoners/by-name/${summonerName}?api_key=YOUR_API_KEY`); // 先检查请求是否成功,避免拿到错误数据 if (!response.ok) { throw new Error(`请求失败,状态码:${response.status}`); } // 等待响应体解析成JSON const summonerData = await response.json(); return summonerData.id; // 返回真实的召唤师ID,不是Promise } catch (error) { console.error("获取召唤师ID出错:", error); throw error; // 把错误抛出去,让上层处理 } }
同理,你的第二个核心函数(比如获取玩家战绩的getSummonerStats)也要改成同样的async格式:
async function getSummonerStats(summonerRegion, summonerID) { try { const response = await fetch(`https://${summonerRegion}.api.riotgames.com/lol/league/v4/entries/by-summoner/${summonerID}?api_key=YOUR_API_KEY`); if (!response.ok) throw new Error(`请求失败,状态码:${response.status}`); const statsData = await response.json(); return statsData; // 返回玩家段位、胜率等真实数据 } catch (error) { console.error("获取玩家数据出错:", error); throw error; } }
第二步:用主async函数统一控制数据获取和渲染时序
关键来了:所有渲染逻辑必须放在所有异步请求完成之后。你需要一个主函数,先等待所有数据都拿到手,再调用渲染函数:
// 主函数:负责串联数据获取和页面渲染 async function loadAndRenderData() { // 先获取用户输入的区域、玩家名字(假设你有对应的输入控件) const targetRegion = document.getElementById("region-select").value; const mainSummoner = document.getElementById("main-summoner").value; const compareSummoner = document.getElementById("compare-summoner").value; try { // 方式1:串行获取两个玩家的数据(适合新手理解) const mainPlayerID = await getSummonerID(targetRegion, mainSummoner); const mainPlayerStats = await getSummonerStats(targetRegion, mainPlayerID); const comparePlayerID = await getSummonerID(targetRegion, compareSummoner); const comparePlayerStats = await getSummonerStats(targetRegion, comparePlayerID); // 所有数据都拿到了!现在才调用渲染函数 renderStatsComparison(mainPlayerStats, comparePlayerStats); // 方式2:并行获取(速度更快,适合进阶) // 同时请求两个玩家的ID,不用等第一个完成再请求第二个 // const [mainID, compareID] = await Promise.all([ // getSummonerID(targetRegion, mainSummoner), // getSummonerID(targetRegion, compareSummoner) // ]); // // 同时请求两个玩家的战绩 // const [mainStats, compareStats] = await Promise.all([ // getSummonerStats(targetRegion, mainID), // getSummonerStats(targetRegion, compareID) // ]); // renderStatsComparison(mainStats, compareStats); } catch (error) { // 出错时给用户提示,比如显示在页面上 document.getElementById("error-msg").textContent = `加载失败:${error.message}`; } } // 纯渲染函数:只负责把数据填充到页面,不处理异步 function renderStatsComparison(player1, player2) { // 示例:填充玩家1的段位 document.getElementById("player1-rank").textContent = `${player1[0].tier} ${player1[0].rank}`; // 示例:填充玩家2的胜率 const winRate = Math.round((player2[0].wins / (player2[0].wins + player2[0].losses)) * 100); document.getElementById("player2-winrate").textContent = `${winRate}%`; // 其他渲染逻辑... } // 绑定按钮点击事件,触发数据加载和渲染 document.getElementById("load-btn").addEventListener("click", loadAndRenderData);
你可能踩过的坑(划重点)
- 忘记加await:调用async函数时如果不加await,拿到的是Promise对象,不是真实数据,渲染自然出错
- 渲染逻辑提前执行:把render函数放在async函数外面,或者放在await之前,导致渲染时数据还没准备好
- 错误处理缺失:某个请求失败后没有捕获错误,导致整个流程卡住,用户看不到任何反馈
最后提个小提醒:Riot的API有请求频率限制,记得在代码里处理rate limit的问题(比如加请求间隔、缓存数据),避免被限流哦!
内容的提问来源于stack exchange,提问作者Neil R
相关产品推荐
相关产品推荐

