Javascript-一个函数依赖于其他首先运行的函数

时间:2019-04-03 03:11:32

标签: javascript d3.js plotly.js

前面的免责声明:我主要使用Python工作,我敢肯定我的问题与我对Javascript异步性质的基本误解有关。如果是这样,则不胜感激。

无论哪种方式,我的特定问题是使用plotly和d3从csv加载数据然后进行绘制。这是一个示例csv(在我的代码中为“ fake_data.csv”)

x,y,z
0.0,0.0,5.4
0.0,2.1,4.1
3.2,1.5,3.2

我有一个index.html,如下:

<head>
    <script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
</head>
<body>
    <div id="graph" style="width:100%;height:100%"></div>
    <script src="scatter.js"></script>        
</body>

然后我有我的scatter.js脚本,该脚本称为。它从一个简单的辅助函数开始,以解压缩csv:

function unpack(rows, key) {
    return rows.map(function(row) 
        { return row[key]; }); 
}

对于绘图功能,如果我只是这样做的话,就可以正常工作:

Plotly.d3.csv('fake_data.csv', function(err, rows){
    var x = unpack(rows , 'x');
    var y = unpack(rows , 'y');
    var z = unpack(rows , 'z');
    Plotly.plot('graph', [
      {
              type: 'scatter3d',
              mode: 'lines',
              x: x,
              y: y,
              z: z
    }], {
      height: 640
    });
});

但是我需要能够加载多个csv以便将所有必要的信息获取到绘图中。因此,我尝试将其包装为两个函数,并像这样调用它们:

var x;
var y;
var z;
function getData(filename) {
    Plotly.d3.csv(filename, function(err, rows){
        x = unpack(rows , 'x');
        y = unpack(rows , 'y');
        z = unpack(rows , 'z'); 
    });
}

function makePlot() {
    console.log(x)
    Plotly.plot('graph', [
      {
              type: 'scatter3d',
              mode: 'markers',
              x: x,
              y: y,
              z: z
    }], {
      height: 640
    });
}

getData('fake_data.csv');
makePlot();

这什么都不呈现。 console.log(x)内的makePlot()打印undefined

但是在页面加载后在控制台(我正在使用Chrome开发人员工具)中输入makePlot()时,它可以正常工作!那我在做什么错?我的猜测是makePlot()被称为“ {{1}”之前”,因此getData()中还没有值。但是我无法正确地告诉Javascript调用一个函数然后在其后调用另一个函数

在此先感谢您的任何建议。这感觉像是一个非常基本的概念,我只是把头撞在墙上。

2 个答案:

答案 0 :(得分:2)

D3使用旧式回调方法。 因此,您可以执行该模型或将其包装在Promise中。

var x;
var y;
var z;

function getData(filename, resolve, reject) {
  if (!reject) reject = (err) => console.log(err);
  return new Promise((resolve, reject) => {
    Plotly.d3.csv(filename, function(err, rows) {
      x = unpack(rows, 'x');
      y = unpack(rows, 'y');
      z = unpack(rows, 'z');
      // if error
      reject(err);
      // resolve here
      resolve();
    });
  });
}

function makePlot() {
  console.log(x)
  Plotly.plot('graph', [{
    type: 'scatter3d',
    mode: 'markers',
    x: x,
    y: y,
    z: z
  }], {
    height: 640
  });
}

getData('fake_data.csv', makePlot);

答案 1 :(得分:1)

仅是对Bibberty的回答的补充:如果您确切知道要下载用于执行makePlot()的csv文件,则可以简单地使用Promise.all来确保在绘制之前显示所有文件。

var x;
var y;
var z;

function getData(filename, resolve, reject) {
  if (!reject) reject = (err) => console.log(err);
  return new Promise((resolve, reject) => {
    Plotly.d3.csv(filename, function(err, rows) {
      x = unpack(rows, 'x');
      y = unpack(rows, 'y');
      z = unpack(rows, 'z');
      // if error
      if (err instanceof Error) {
        reject(err);
      } else {
        // resolve here
        resolve(true); // return true to check resolve status
      }
    });
  });
}

function makePlot() {
  console.log(x)
  Plotly.plot('graph', [{
    type: 'scatter3d',
    mode: 'markers',
    x: x,
    y: y,
    z: z
  }], {
    height: 640
  });
}

var promise1 = getData('fake_data.csv');
var promise2 = getData('fake_data2.csv');
var promise3 = getData('fake_data3.csv');

Promise.all([
  promise1,
  promise2,
  promise3
]).then(function(values) {
  // check if all promises are resolved
  if (values.every(function(value) { return value == true })) {
    makePlot();
  }
})