如何在map内嵌套axios调用全部完成后执行指定函数?
你这段代码的问题在于所有异步请求都没被正确等待,导致processData在数据更新完成前就被调用了。核心原因是异步操作的Promise没有被收集和等待,嵌套的请求也没做await处理。
修正方案及代码
// 假设这段代码在React的useEffect钩子内 useEffect(() => { const fetchAndUpdateData = async () => { // 深拷贝原数据,避免直接修改本地JSON的原始内容 const updatedData = JSON.parse(JSON.stringify(JSONDATA)); // 收集所有异步请求的Promise,用于统一等待 const allRequestPromises = []; updatedData.forEach(player => { player.games.forEach(game => { // 把单个游戏的异步请求包装成Promise const singleGameTask = async () => { try { // 第一层请求:获取对应游戏的详情页URL const baseRes = await axios.get(BASE_URL); const $ = cheerio.load(baseRes.data); // 注意:原代码的bContent应该是页面内的选择器,这里假设是$('.b-content')之类的,需根据实际调整 const sectionContent = $('.b-content').find(`[data-game-id="${game.gameId}"]`); const gamePageUrl = sectionContent.attr('href'); // 第二层请求:获取游戏内的得分数据 const gameRes = await axios.get(gamePageUrl); const $game = cheerio.load(gameRes.data); const pointsElement = $game('table#player_table tbody tr [data-stat=points_scored]'); game.pointsScored = pointsElement.html()?.toString() || '0'; } catch (err) { console.error(`更新游戏${game.gameId}数据失败:`, err); // 失败时可以给默认值,避免数据缺失 game.pointsScored = '0'; } }; allRequestPromises.push(singleGameTask()); }); }); // 等待所有异步请求全部完成 await Promise.all(allRequestPromises); // 所有数据更新完毕后,再执行处理逻辑 processData(updatedData); }; fetchAndUpdateData(); }, []); // 根据实际需求添加useEffect的依赖项
关键改动说明
- 深拷贝原数据:避免直接修改本地JSON文件的原始数据,防止后续使用原数据时出现异常
- 收集所有Promise:把每个游戏的异步请求包装成Promise并加入数组,确保所有请求都被追踪
- 统一等待所有请求:用
Promise.all()等待数组内所有Promise完成,保证所有pointsScored都更新后才执行processData - 简化异步流程:去掉嵌套的独立async函数,把两层请求合并到一个async任务里,用
await替代.then,代码逻辑更清晰 - 容错处理:给每个请求加
try/catch,单个请求失败不会阻断整个流程,还能设置默认得分值
内容的提问来源于stack exchange,提问作者D.D
相关产品推荐
相关产品推荐

