D3技术咨询:如何传递Promise.all返回的数据及地图未显示问题排查
我来帮你拆解这两个问题,一步步解决:
问题一:如何在D3中传递Promise.all返回的数据
你现在用了async/await处理Promise.all,这种方式已经比传统回调更简洁了。目前你的data和geo只在chart函数内部可用,要进一步传递的话,有两种实用方式:
方式一:在async函数内部直接处理数据
把原本放在ready函数里的逻辑直接移到chart函数中就行——因为await已经确保数据加载完成,完全不需要再用回调函数:async function chart() { const [data, geo] = await Promise.all([ d3.json(promises[0]), d3.json(promises[1]) ]) console.log("data", data) console.log("geo", geo) // 这里直接处理地图数据,替代原来的ready函数 let topoobject = topojson.feature(geo, geo.objects.counties); let counties = topoobject.features; // 后续的绘制逻辑也直接写在这里 } chart()方式二:将数据返回给外部调用者
如果需要在其他函数中复用这些数据,可以让chart函数返回数据,然后在调用时处理:async function chart() { return await Promise.all([ d3.json(promises[0]), d3.json(promises[1]) ]) } // 调用chart函数并处理返回的数据 chart().then(([data, geo]) => { console.log("data", data) console.log("geo", geo) // 在这里执行地图绘制逻辑 let topoobject = topojson.feature(geo, geo.objects.counties); let counties = topoobject.features; })
注意:你原来的ready函数用了传统的error-first回调,和async/await写法不兼容,建议统一用一种异步处理方式,避免逻辑混乱。
问题二:排查地图未显示的问题
看你的代码,地图没显示主要有几个核心问题,我帮你逐个梳理修复:
ready函数从未被调用
你定义了ready函数,但没有在任何地方执行它,而且它的回调参数和async/await加载的数据完全没关联,导致地图处理逻辑根本没运行。缺少地图绘制的核心步骤
就算数据加载完成、处理了TopoJSON,你也没有把生成的路径添加到DOM中,也没用到d3.geoPath()来生成地理路径。异步逻辑混用导致的问题
同时用async/await和传统D3回调函数,容易造成数据不匹配,建议统一用async/await。
下面是修复后的完整示例:
// 假设promises已经定义好对应的有效URL async function chart() { const [data, geo] = await Promise.all([ d3.json(promises[0]), d3.json(promises[1]) ]) console.log("data", data) console.log("geo", geo) // 创建SVG容器(如果页面没有现成的,就动态生成) const svg = d3.select("body").append("svg") .attr("width", 800) .attr("height", 600); // 初始化geoPath生成器 const path = d3.geoPath(); // 处理TopoJSON数据 const topoobject = topojson.feature(geo, geo.objects.counties); const counties = topoobject.features; // 绘制县的路径 svg.selectAll("path") .data(counties) .enter() .append("path") .attr("d", path) // 用geoPath生成路径 .attr("fill", "#ccc") // 设置填充色,确保能看到 .attr("stroke", "#fff"); // 设置边框区分区域 } // 调用chart函数启动整个流程 chart();
另外还要排查几个细节:
- 确认
promises数组里的URL能正确返回数据,看浏览器控制台Network标签,检查请求是否成功。 - 确认
geo.objects.counties是正确的TopoJSON对象路径——可以通过console.log(geo)查看数据结构,要是对象名不是counties,得改成对应名称。 - 确保SVG容器有足够尺寸,不然地图可能显示在视口外。
内容的提问来源于stack exchange,提问作者DeanWinchester88
相关产品推荐
相关产品推荐

