gpt4 book ai didi

javascript - 使用 D3.js 创建数据的同步加载并在加载后绘制

转载 作者:行者123 更新时间:2023-11-30 08:19:18 24 4
gpt4 key购买 nike

我已经到了我认为我不理解正确的事件回调的阶段。我正在使用 d3.js v5,我的问题如下。我有一个解析 tsv 文件并使用 d3.tsv 函数将数据添加到全局数组 selectedData 的函数,该函数在函数 addData:

//function takes filename and data description to add to the selectedData global variable
function addData(filename, dataDesc) {
d3.tsv(filename, type).then ((data) => {
data.forEach(e => {
var obj = {
Title: dataDesc,
ID: e.ID,
Value: e.Value,
}
selectedData.push(obj);
});
});
}

function type(d) {
d.Value = +d.Value;
}

现在我使用这个函数来添加单个数据文件,或者可以多次调用它来将多个数据文件中的数据添加到这个全局变量中。全局变量用于许多其他功能,但作为开始,它用于生成条形图。

对于添加单个文件,我想在将数据添加到全局变量后生成一个条形图。为此,我使用以下函数:

//functions adds one data file
function addOneData() {
filename = userfile; //gets the user file name based on <input> element using the FileReader api
dataDesc = document.getElementById('file_title').value; //gets the Descriptive Title of the data
addData(filename, dataDesc); //add data to the global variable of selectedData
drawBarChart(); //draws a grouped bar chart based on the global array of selectedData
}

我有一个类似的函数,它循环遍历多个数据文件的数组,并将它们添加到具有不同文件名dataDesc 的全局变量中。对于多个文件,我不希望在每个文件之后进行绘图,这就是为什么 drawBarChart 函数不是 addData 函数的一部分的原因。

现在我的问题是 addDatadrawBarChart 的函数是异步运行的,因此 drawBarChart 在数据添加到selectedData 全局变量。所以我的问题是,我怎样才能使它同步或使用 promise 的力量?我一直在尝试 promises 和 async/await,但感觉我错过了一些关键概念。任何帮助表示赞赏。谢谢。

最佳答案

“创建数据的同步加载” 在这种情况下没有多大意义......取而代之的是,接受异步代码的本质。

另外,你说:

For the multiple files I do not want the drawing to happen after each file, which is why the drawBarChart function is not a part of the addData function.

但这就是您的 addOneData 函数现在正在做的事情:它正在为每个文件调用 drawBarChart(如您所知,由于 的异步性质,这是错误的添加数据).

那么,让我们解决您的两个问题,异步代码和加载多个文件后调用 drawBarChart

1。异步代码

一个简单的解决方案是将 drawBarchart 作为回调传递给另一个 then 方法,如下所示:

function addData(filename, dataDesc, callback) {
d3.json(filename).then((data) => {
data.forEach(e => {
var obj = {
Title: dataDesc,
Value: e
}
selectedData.push(obj);
});
}).then(callback)
};

这是一个我在网上创建的非常简单的 JSON 的演示(需要 d3.json,但一般原理与您的 d3.tsv 相同,它就像您的案例的 TSV 一样工作):

var selectedData = [];

addOneData();

function addData(filename, dataDesc, callback) {
d3.json(filename).then((data) => {
data.forEach(e => {
var obj = {
Title: dataDesc,
Value: e
}
selectedData.push(obj);
});
}).then(callback)
};

function addOneData() {
filename = "https://api.myjson.com/bins/m1vsl";
dataDesc = "FooBar"
addData(filename, dataDesc, drawBarChart);
};

function drawBarChart() {
console.log(selectedData)
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

2。多个文件

正如您提到的,您可能有很多文件,但您只想调用一次 drawBarChart。在这种情况下,使用 Promise.all 和一个包含文件名的数组:

function addData(filenames, dataDesc, callback) {
Promise.all(filenames.map(d => d3.json(d))).then((alldata) => {
alldata.forEach(data => {
data.forEach(e => {
var obj = {
Title: dataDesc,
Value: e
}
selectedData.push(obj);
});
});
}).then(callback)
};

这是演示:

var selectedData = [];

addAllData();

function addData(filenames, dataDesc, callback) {
Promise.all(filenames.map(d => d3.json(d))).then((alldata) => {
alldata.forEach(data => {
data.forEach(e => {
var obj = {
Title: dataDesc,
Value: e
}
selectedData.push(obj);
});
});
}).then(callback)
};

function addAllData() {
filenames = ["https://api.myjson.com/bins/m1vsl", "https://api.myjson.com/bins/rncvp"];
dataDesc = "FooBar";
addData(filenames, dataDesc, drawBarChart);
};

function drawBarChart() {
console.log(selectedData)
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

关于javascript - 使用 D3.js 创建数据的同步加载并在加载后绘制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56640772/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com