You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

d3.csv读取的全局数组在函数外部显示undefined问题求助

问题:全局数组在函数外部显示undefined,无法加载CSV数据到Google地图标记

使用D3.js v7和Google Maps JavaScript API时,声明了全局数组存储CSV数据,但在读取函数外部访问数组元素时显示undefined,无法生成地图标记。CSV格式为Project_Name, Artist, Lat, Long,包含约300条数据。

原代码如下:

// Request needed libraries.
const { Map, InfoWindow } = await google.maps.importLibrary("maps");
const { LatLng } = await google.maps.importLibrary("core");
const { AdvancedMarkerElement, PinElement } = await google.maps.importLibrary("marker");

//Global Vars
let map;
let projectName = [];
let artist = [];
let lat = [];
let long = [];
let markers = [];


async function data() {
  d3.csv("/data/single.csv", function(d) {
    return {
      projectName: +d.Project_Name,
      artist: +d.Artist,
      lat: +d.Latitude,
      long: +d.Longitude,
    }
  }).then(function(d) {
    for (var i = 0; i < d.length; i++) {
      projectName[i] = d[i].Project_Name;
      artist[i] = d[i].Artist;
      lat[i] = parseFloat(d[i].Latitude);
      long[i] = parseFloat(d[i].Longitude);
    }
  });
}



function createMarkers(m){
  for (var z=0; z < lat.length; z++) {
    markers[z] = new google.maps.Marker({
      position: new google.maps.LatLng(lat[z], long[z]),
      map: m,
      title: projectName[z],
    });
  } 
}

async function initMap() {
  
  const map = new Map(document.getElementById("map"), {
    zoom: 11,
    center: { lat: 37.4239163, lng: -122.0947209 },
    mapId: "[MAP ID]",
    mapTypeControl: false,
  });
  const infoWindow = new google.maps.InfoWindow({
    content: "",
    disableAutoPan: true,
  });
  
  //READ CSV FILE
  data();
  
  //MARKERS
  createMarkers(map);
  
}

initMap();

尝试过await和setTimeout但未解决,使用setTimeout后值变为NaN。


解决方案

问题根源

  1. 异步执行顺序错误:data()是异步函数但未返回Promise,且initMap中调用data()时没有等待其执行完成,导致createMarkers先运行,此时全局数组还未被CSV数据填充,因此显示undefined。
  2. D3数据转换错误:在d3.csv的转换函数中,用+将Project_Name和Artist(字符串类型)强制转为数字,导致这两个字段变成NaN,后续赋值自然无法得到正确内容。

修改步骤

  1. 修复D3数据转换逻辑:移除Project_Name和Artist前的+,保留字符串类型;Latitude和Longitude直接用+转数字,无需后续再调用parseFloat。
  2. 让data()返回Promise:直接返回d3.csv的调用结果,确保可以用await等待数据加载完成。
  3. 在initMap中等待data()完成:调用data()时添加await,确保数组填充完成后再执行createMarkers。

修改后的完整代码

// Request needed libraries.
const { Map, InfoWindow } = await google.maps.importLibrary("maps");
const { LatLng } = await google.maps.importLibrary("core");
const { AdvancedMarkerElement, PinElement } = await google.maps.importLibrary("marker");

//Global Vars
let map;
let projectName = [];
let artist = [];
let lat = [];
let long = [];
let markers = [];


// 修改data函数,返回Promise并修复数据转换
async function data() {
  return d3.csv("/data/single.csv", function(d) {
    return {
      projectName: d.Project_Name, // 去掉+,保留字符串
      artist: d.Artist, // 去掉+,保留字符串
      lat: +d.Latitude, // 直接转数字
      long: +d.Longitude // 直接转数字
    }
  }).then(function(d) {
    for (var i = 0; i < d.length; i++) {
      projectName[i] = d[i].projectName;
      artist[i] = d[i].artist;
      lat[i] = d[i].lat;
      long[i] = d[i].long;
    }
  });
}

function createMarkers(m){
  for (var z=0; z < lat.length; z++) {
    markers[z] = new google.maps.Marker({
      position: new google.maps.LatLng(lat[z], long[z]),
      map: m,
      title: projectName[z],
    });
  } 
}

async function initMap() {
  
  const map = new Map(document.getElementById("map"), {
    zoom: 11,
    center: { lat: 37.4239163, lng: -122.0947209 },
    mapId: "[MAP ID]",
    mapTypeControl: false,
  });
  const infoWindow = new google.maps.InfoWindow({
    content: "",
    disableAutoPan: true,
  });
  
  // 等待数据加载完成
  await data();
  
  // 数据填充后再创建标记
  createMarkers(map);
  
}

initMap();

进一步优化建议

可以去掉全局数组,直接将D3返回的数据传递给createMarkers,避免全局变量带来的潜在问题:

async function data() {
  return d3.csv("/data/single.csv", function(d) {
    return {
      projectName: d.Project_Name,
      artist: d.Artist,
      lat: +d.Latitude,
      long: +d.Longitude
    }
  });
}

// 修改createMarkers,直接接收数据数组
function createMarkers(m, data){
  data.forEach(item => {
    const marker = new google.maps.Marker({
      position: new google.maps.LatLng(item.lat, item.long),
      map: m,
      title: item.projectName,
    });
    markers.push(marker);
  });
}

async function initMap() {
  // ... 地图初始化代码 ...
  
  // 获取数据后直接传递给createMarkers
  const csvData = await data();
  createMarkers(map, csvData);
}

内容的提问来源于stack exchange,提问作者Sydney Linford

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 03:23:11