如何在d3.json异步回调外向数组推送元素并判断循环执行完毕
解决方案
核心思路是将所有异步请求包装为Promise对象,通过Promise.all自动判断所有请求是否全部完成,不需要手动设置延迟。
d3 v5及以上版本的d3.json本身返回Promise,可直接配合async/await语法使用,修改后代码如下:
async function update_league_picks (selected_league){ // 生成所有第一层page请求的Promise列表 const pagePromises = Array.from({length:20}, (_,i)=> d3.json(`file1_page=${i+1}.json`)) // 等待所有第一层请求返回 const allPageData = await Promise.all(pagePromises) const league_picks = [] // 存储所有第二层id请求的Promise const idPromises = [] allPageData.forEach(league_players => { const players_page = league_players["standings"]["results"] // 遍历当前页的所有球员,生成第二层请求 players_page.forEach(player => { const team_id = player.entry // 注意原代码这里你写的是${j},如果是要传team_id需要改成${team_id},请自行核对逻辑 idPromises.push( d3.json(`file2_id=${team_id}.json`).then(opp_data => { league_picks.push({"active_chip":opp_data.active_chip}) }) ) }) }) // 等待所有第二层请求全部完成 await Promise.all(idPromises) // 此时数组已经填充完成,可以直接使用 console.log(league_picks) }
注意事项
- 原代码中第二层请求的路径写的是
file2_id=${j}.json,按照业务逻辑应该是file2_id=${team_id}.json,请自行核对修改 - 若使用的是v5以下版本的d3,可手动将回调式的d3.json封装为Promise,封装方式如下:
function fetchJson(url) { return new Promise((resolve, reject) => { d3.json(url, (error, data) => { if (error) return reject(error) resolve(data) }) }) }
之后将代码中所有d3.json替换为fetchJson即可正常运行。
内容的提问来源于stack exchange,提问作者Bojan Stavric
相关产品推荐
相关产品推荐

