0

0

如何在 D3 v7 中正确处理 CSV 异步加载并确保全局数组可用

聖光之護

聖光之護

发布时间:2026-01-03 22:29:02

|

761人浏览过

|

来源于php中文网

原创

如何在 D3 v7 中正确处理 CSV 异步加载并确保全局数组可用

本文详解 d3 v7 中 `d3.csv()` 的异步特性导致全局数组在函数外仍为 `undefined` 的根本原因,并提供基于 `async/await` 的标准解决方案,确保数据加载完成后再执行地图标记等依赖操作。

D3 v7 的 d3.csv() 返回一个 Promise,而非同步填充数据——这是问题的核心。您声明了全局数组(如 projectName = []),并在 data() 函数中尝试赋值,但由于未等待 Promise 解析完成,createMarkers() 就已执行,此时全局数组仍是空的(访问 lat[z] 自然得到 undefined,进而导致 NaN 或报错)。

要修复此问题,必须让 initMap() 等待 CSV 加载完毕。关键修改有三处:

  1. data() 函数需返回 d3.csv() Promise,并统一使用现代箭头函数解析器(避免旧式回调嵌套);
  2. initMap() 必须 await data(),确保全局数组已填充;
  3. createMarkers() 需接收 map 实例作为参数(因 map 在 initMap() 内定义,非全局)。

以下是修正后的完整代码(含健壮性增强):

慧中标AI标书
慧中标AI标书

慧中标AI标书是一款AI智能辅助写标书工具。

下载
// 请求 Google Maps 库
const { Map, InfoWindow } = await google.maps.importLibrary("maps");
const { LatLng } = await google.maps.importLibrary("core");
const { AdvancedMarkerElement, PinElement } = await google.maps.importLibrary("marker");

// 全局数组(保持声明)
let projectName = [];
let artist = [];
let lat = [];
let long = [];
let markers = [];

// ✅ 修正:data() 返回 Promise,使用 d3.csv 的现代解析方式
async function data() {
  return d3.csv("/data/single.csv", (d) => ({
    projectName: d.Project_Name,  // 字符串,勿用 +d.Project_Name(会转 NaN)
    artist: d.Artist,
    lat: parseFloat(d.Latitude),   // 显式 parseFloat 更安全
    long: parseFloat(d.Longitude),
  }));
}

// ✅ 修正:createMarkers 接收 map 参数,避免作用域问题
function createMarkers(m) {
  for (let z = 0; z < lat.length; z++) {
    if (isNaN(lat[z]) || isNaN(long[z])) continue; // 跳过无效坐标
    markers.push(
      new google.maps.Marker({
        position: { lat: lat[z], lng: long[z] }, // 直接传对象,更简洁
        map: m,
        title: projectName[z] || "Unknown Project",
      })
    );
  }
}

// ✅ 修正:initMap 使用 async/await,确保顺序执行
async function initMap() {
  const map = new Map(document.getElementById("map"), {
    zoom: 11,
    center: { lat: 37.4239163, lng: -122.0947209 },
    mapId: "[MAP ID]",
    mapTypeControl: false,
  });

  try {
    // ? 关键:等待 CSV 加载并填充全局数组
    const csvData = await data();

    // 填充全局数组(推荐:直接赋值,避免手动循环索引)
    projectName = csvData.map(d => d.projectName);
    artist = csvData.map(d => d.artist);
    lat = csvData.map(d => d.lat);
    long = csvData.map(d => d.long);

    // 创建标记
    createMarkers(map);

  } catch (error) {
    console.error("CSV 加载失败:", error);
    alert("地图数据加载异常,请检查 CSV 文件路径和格式。");
  }
}

initMap();

注意事项与最佳实践:

  • ❌ 避免在 d3.csv 回调中混用旧式 function(d){} 和 +d.xxx 类型转换(数字字段缺失时易得 NaN);✅ 推荐用 parseFloat() 并配合 isNaN() 校验;
  • ❌ 不要将 map 声明为全局变量(违反封装原则且易引发冲突);✅ 通过参数传递更清晰、可测试;
  • ✅ 使用 try/catch 捕获 CSV 加载异常(如 404、格式错误),提升应用鲁棒性;
  • ✅ 优先用 csvData.map() 批量赋值,比手动 for 循环更简洁、不易越界。

遵循以上模式,即可彻底解决“全局数组在异步加载后仍为 undefined”的问题,确保地理数据与地图渲染的严格时序依赖。

相关专题

更多
全局变量怎么定义
全局变量怎么定义

本专题整合了全局变量相关内容,阅读专题下面的文章了解更多详细内容。

73

2025.09.18

python 全局变量
python 全局变量

本专题整合了python中全局变量定义相关教程,阅读专题下面的文章了解更多详细内容。

96

2025.09.18

golang map内存释放
golang map内存释放

本专题整合了golang map内存相关教程,阅读专题下面的文章了解更多相关内容。

73

2025.09.05

golang map相关教程
golang map相关教程

本专题整合了golang map相关教程,阅读专题下面的文章了解更多详细内容。

25

2025.11.16

golang map原理
golang map原理

本专题整合了golang map相关内容,阅读专题下面的文章了解更多详细内容。

57

2025.11.17

java判断map相关教程
java判断map相关教程

本专题整合了java判断map相关教程,阅读专题下面的文章了解更多详细内容。

32

2025.11.27

C++类型转换方式
C++类型转换方式

本专题整合了C++类型转换相关内容,想了解更多相关内容,请阅读专题下面的文章。

291

2025.07.15

undefined是什么
undefined是什么

undefined是代表一个值或变量不存在或未定义的状态。它可以作为默认值来判断一个变量是否已经被赋值,也可以用于设置默认参数值。尽管在不同的编程语言中,undefined可能具有不同的含义和用法,但理解undefined的概念可以帮助我们更好地理解和编写程序。本专题为大家提供undefined相关的各种文章、以及下载和课程。

4071

2023.07.31

python设置中文版教程合集
python设置中文版教程合集

本专题整合了python改成中文版相关教程,阅读专题下面的文章了解更多详细内容。

1

2026.01.05

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Git 教程
Git 教程

共21课时 | 2.4万人学习

Git版本控制工具
Git版本控制工具

共8课时 | 1.5万人学习

Git中文开发手册
Git中文开发手册

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号