D3 for循环中的代码执行不是线性的(?)

时间:2014-06-12 22:39:06

标签: javascript svg d3.js

我在D3中做了一件非常简单的事情,但是我遇到了代码执行顺序的奇怪问题。我正在使用一系列图像名称,循环遍历它们,并将每个svg添加到父svg作为g元素。一切都很好。这是代码:

var names = ['a', 'b', 'c']
var over = d3.select('#overlay');
var w = 20;
for (var i = names.length - 1; i >= 0; i--) {
  var x = w * i + w
  console.log('1. '+ x)
  d3.xml(names[i]+'.svg', function(error, xml) {
    console.log('2. '+ x)
    over.append('g')
    .attr('transform','translate('+ x +','+ 20 +')')
    .html(xml.getElementsByTagName('svg')[0].innerHTML)
  })
}

但是,我遇到的变换问题都是一样的,并决定记录x来检查它。日志应该是这样的:

1. 60
2. 60
1. 40
2. 40
1. 20
2. 20

相反,它记录了这个:

1. 60
1. 40
1. 20
2. 20
2. 20
2. 20

有什么可能让这样的运行失序? d3.xml调用是否异步?我无法理解。

1 个答案:

答案 0 :(得分:2)

d3.xml()是异步函数,并不是按预期顺序启动的,但稍后就足够了,循环结束并且x的值为20.

您必须使用例如:

对值x进行闭包
  (function (x) {
      d3.xml(names[i]+'.svg', function(error, xml) {
        console.log('2. '+ x)
        over.append('g')
        .attr('transform','translate('+ x +','+ 20 +')')
        .html(xml.getElementsByTagName('svg')[0].innerHTML)
      });
  })(x)

这样你就会进入控制台日志:

1. 60
1. 40
1. 20
2. 60
2. 40
2. 20