首页 > 解决方案 > 将我的所有代码放入 d3.csv() 的参数中是否有问题?

问题描述

我正在学习 d3.js,最近遇到了无法访问d3.csv()函数内部变量的问题。我刚刚在程序开始时初始化了我的变量,以使我的所有变量都成为全局变量。

这让我想知道如果我只是将所有代码放入d3.csv函数中是否存在问题,甚至不需要在代码开头初始化我的变量,所以它看起来像:

d3.csv(data.csv, (data)=>{
    all of my code
});

这是否有缺点(假设我只使用一个 CSV 文件)或者保留不需要d3.csv方法外部数据的代码是否有一些好处?

标签: javascriptd3.js

解决方案


注意:由于您询问的是d3.csv我假设您使用的是 D3 v4 或更低版本的回调,因为 D3 v5 使用了 Promise 的then方法。然而,道理是一样的。


最重要的信息是d3.csv,与所有其他 D3 XHR 方法一样,它是一个异步函数。这意味着回调中的所有内容仅在下载和解析 CSV 后运行。

//Outside the callback
//Code here runs immediately

d3.csv("example.csv", (data) => {
    //Inside the callback
    //Code here runs only after the CSV was downloaded and parsed
});

//Outside the callback
//Even if these lines come after d3.csv, code here runs before the code inside the callback

顺便说一句,这解释了您最初的抱怨(“...我最近遇到了无法访问d3.csv()函数内部变量的问题”)。这个答案是关于该主题的好读物。

考虑到这一点,我们必须以这样一种方式优化代码,以便可以立即创建/设置不依赖于数据的东西,因为如果我们将它们放在回调中,我们将毫无理由地浪费时间。

简而言之,您可以在回调之外放置一些东西,例如(但不限于):

  • 选择/创建 SVG、画布或 HTML 容器
  • 秤(带范围)
  • 轴发生器
  • 线路发生器
  • 区域生成器
  • 堆栈生成器
  • 饼图生成器
  • 直方图生成器
  • 地图投影
  • 层次布局
  • 格式(如时间格式)
  • 力模拟器
  • 拖动行为
  • 缩放行为

所有这些都不依赖于任何数据。对于其中一些(如线生成器、区域生成器、堆栈生成器等),您将在获得数据后传递数据。

然后,在回调中,您放置依赖于数据的所有内容,例如(但不限于):

  • 更新、进入和退出选择
  • Scale 的领域
  • 调用轴生成器
  • 设置模拟的节点和链接
  • 巢穴
  • 将数据传递给线生成器、区域生成器、堆栈生成器等...
  • 转换(取决于数据)
  • 事件侦听器(取决于数据)

如您所见,如果您将所有内容放入回调中,您将拥有一堆可以立即运行的方法,但是,它们只是坐在那里不必要地等待数据下载。


推荐阅读