前面的免责声明:我主要使用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调用一个函数然后在其后调用另一个函数。
在此先感谢您的任何建议。这感觉像是一个非常基本的概念,我只是把头撞在墙上。
答案 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();
}
})