axios.get首次加载无法正常获取数据,刷新正常,求纯JS优化方案
问题描述
页面刷新后数据可正常加载,但首次加载时,依赖前序请求生成的budgetI和bi变量的最后一个axios请求无法正确获取数据。尝试过添加.finally、async/await但未解决,需要纯JavaScript解决方案,核心是让最后一个请求等待所有前序异步请求完成后再执行。
原代码
axios.get(`https://api.github.com/repos/${orgEl}/${repoEl}/contents/Transactions/${projectJ}/${fundJ}/${poolJ}`) .then(response => { const data = response.data; console.log('data', data); for (let j in data) { budgetI[j] = data[j].name.replace(/\s/g, '-'); //* over here is the 'budgetI' variable axios.get(`https://api.github.com/repos/${orgEl}/${repoEl}/contents/Transactions/${projectJ}/${fundJ}/${poolJ}/${budgetI[j]}`) .then(response => { const data = response.data; for (let m in data) { axios.get(data[m].download_url) .then(response => { const data = response.data; bi.push(data); //* over here is the 'bi' variable }) .catch(error => console.error(error)).finally(() => { console.log("first load"); }); } }) .catch(error => console.error(error)).finally(() => { console.log("mid load"); }); } }) .catch(error => console.error(error)) .finally(() => { console.log("final load"); }); axios.get(`https://pool.pm/wallet/${walletEl}`) .then(response => { for (let i in bi) { y = bi[i].budget.replace(/\s/g, '-') //* bi value comes from axios.get above for (let j in budgetI) { //* budgetI value comes from axios.get above if ( y == budgetI[j]) { totals[y] = totals[y] + (parseInt(bi[i].ada)); totals.outgoing = totals.outgoing + (parseInt(bi[i].ada)); } } };
解决方案
核心是用Promise.all批量等待所有嵌套异步请求完成,确保budgetI和bi变量完全填充后再执行最后一个请求。改造后的代码如下:
// 封装预算数据加载逻辑为异步函数 async function loadBudgetData() { try { // 第一层请求:获取预算目录列表 const firstResponse = await axios.get(`https://api.github.com/repos/${orgEl}/${repoEl}/contents/Transactions/${projectJ}/${fundJ}/${poolJ}`); const firstData = firstResponse.data; console.log('data', firstData); // 收集所有第二层请求的Promise const budgetPromises = firstData.map(item => { const budgetName = item.name.replace(/\s/g, '-'); budgetI.push(budgetName); // 改用push避免索引异常 // 第二层请求:进入单个预算目录 return axios.get(`https://api.github.com/repos/${orgEl}/${repoEl}/contents/Transactions/${projectJ}/${fundJ}/${poolJ}/${budgetName}`) .then(secondResponse => { const secondData = secondResponse.data; // 收集所有文件下载请求的Promise const filePromises = secondData.map(fileItem => { return axios.get(fileItem.download_url) .then(fileResponse => { bi.push(fileResponse.data); }); }); // 等待当前目录下所有文件请求完成 return Promise.all(filePromises); }); }); // 等待所有预算相关请求全部完成 await Promise.all(budgetPromises); console.log("所有预算数据加载完成"); } catch (error) { console.error(error); } } // 先加载预算数据,完成后再发起钱包请求 loadBudgetData().then(() => { axios.get(`https://pool.pm/wallet/${walletEl}`) .then(response => { for (let i in bi) { const y = bi[i].budget.replace(/\s/g, '-'); for (let j in budgetI) { if (y === budgetI[j]) { // 处理totals初始值为undefined的情况 totals[y] = (totals[y] || 0) + parseInt(bi[i].ada); totals.outgoing = (totals.outgoing || 0) + parseInt(bi[i].ada); } } } }) .catch(error => console.error(error)); });
关键改进点
- 用
async/await替代嵌套then,代码结构更清晰 - 用
Promise.all确保所有异步请求完成后再执行后续逻辑,解决首次加载数据未就绪的问题 - 修复
totals变量可能未初始化的异常(添加|| 0兜底) - 将
budgetI的赋值改为push,避免循环索引带来的潜在问题
内容的提问来源于stack exchange,提问作者Glaxas
相关产品推荐
相关产品推荐

