【问题标题】:Code within d3.json() callback is not executedd3.json() 回调中的代码未执行
【发布时间】:2020-07-03 03:04:24
【问题描述】:

我正在尝试加载一个 GeoJSON 文件并使用它作为 D3 v5 的基础来绘制一些图形。

问题在于浏览器跳过了 d3.json() 调用中包含的所有内容。我尝试插入断点进行测试,但浏览器跳过了它们,我不知道为什么。

代码如下:sn-p。

d3.json("/trip_animate/tripData.geojson", function(data) {

  console.log("It just works");  // This never logs to console.

  //...all the rest
}

代码从最初的console.log() 继续,但我省略了所有代码,因为我怀疑问题出在d3.json 调用本身。

【问题讨论】:

    标签: javascript d3.js


    【解决方案1】:

    d3.json 的签名从 D3 v4 到 v5 具有 changed。它已从现已弃用的模块 d3-request 移至新的 d3-fetch 模块。从 v5 开始,D3 使用 Fetch API 代替旧的 XMLHttpRequest,并反过来采用 Promises 来处理这些异步请求。

    d3.json() 的第二个参数不再是处理请求的回调,而是一个可选的RequestInit 对象。 d3.json() 现在将返回一个 Promise,您可以在其 .then() 方法中处理。

    您的代码因此变为:

    d3.json("/trip_animate/tripData.geojson")
      .then(function(data){
        // Code from your callback goes here...
      });
    

    随着 Fetch API 的引入,调用的错误处理也发生了变化。 v5 之前的版本使用传递给d3.json() 的回调的第一个参数来处理错误:

    d3.json(url, function(error, data) { 
      if (error) throw error;
      // Normal handling beyond this point.
    });
    

    从 D3 v5 开始,如果遇到错误,d3.json() 返回的承诺将被拒绝。因此,可以应用处理这些拒绝的 vanilla JS 方法:

    1. 将拒绝处理程序作为第二个argument 传递给.then(onFulfilled, onRejected)

    2. 使用 .catch(onRejected) 向 Promise 添加拒绝处理程序。

    应用第二种解决方案,您的代码就变成了

    d3.json("/trip_animate/tripData.geojson")
      .then(function(data) {
        // Code from your callback goes here...
      })
      .catch(function(error) {
        // Do some error handling.
      });
    

    【讨论】:

    • @Timmmm,.then 方法可以提供一个可选的第二个函数,如果 promise 最终未实现,则调用该函数:.then(function(data) {}, function(error) {})
    • @Timmmm 或者,您可以使用.catch(function(error) {}),这与 Andrew 的建议大致相同,但更明确。
    • 假设我们不能使用 V5 语法,而必须使用 V4。那我们该怎么办?
    • @3xCh1_23 您只需使用问题中发布的原始代码即可。
    • @altocumulus 不起作用,这就是重点……但找到了一种解决方法,共享起来有点复杂……
    【解决方案2】:

    由于没有一个答案有帮助,我必须自己找到可行的解决方案。我正在使用 v4 并且必须坚持使用它。问题是(在我的情况下)d3.json 第一次工作,但第二次或第三次没有工作(使用 HTML 下拉菜单)。

    这个想法是使用初始函数,然后简单地使用第二个函数

    让数据 = 等待 d3.json("URL");

    而不是

    d3.json("URL", function(data) {

    因此,一般模式变为:

    async function drawWordcloudGraph() {
        let data = await d3.json("URL");
        ...
    }
    
    
    function initialFunction() {
        d3.json("URL", function (data) {
            ...
        });
    }
    
    initialFunction();
    

    我尝试了几种方法,但只有这种方法有效。不确定是否可以简化,请自行测试。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多