JavaScript变量赋值/返回
我正在使用d3.js加载2个csv文件,并希望合并它们。然而,我被一些更基本的东西困住了 我有以下功能,工作正常:JavaScript变量赋值/返回,javascript,d3.js,Javascript,D3.js,我正在使用d3.js加载2个csv文件,并希望合并它们。然而,我被一些更基本的东西困住了 我有以下功能,工作正常: function loadData(file) { d3.csv(file, function (d){...}, function (data) {displayData(data);}); } 现在,我正试图以一种方式重构代码,即使用loadData()返回data对象,这样我可以调用它两次,合并data数组,并使用合并的数组调用displayData
function loadData(file) {
d3.csv(file, function (d){...},
function (data) {displayData(data);});
}
现在,我正试图以一种方式重构代码,即使用loadData()
返回data
对象,这样我可以调用它两次,合并data
数组,并使用合并的数组调用displayData()
我尝试返回数据
:
function loadData(file) {
d3.csv(file, function (d){...},
function (data) {return data});
return data;
}
使用全局变量
var gdata1 = {};
var gdata2 = {};
function loadData(file) {
d3.csv(file, function (d){...},
function (data) {gdata = data});
gdata2 = data;
}
var gdata1 = {};
var gdata2 = {};
function loadData(file) {
d3.csv(file, function (d){...},
function (data) {gdata = data; displayData(gdata)});
}
在许多其他事情中,似乎没有什么起作用
令人惊讶的是
使用全局变量
var gdata1 = {};
var gdata2 = {};
function loadData(file) {
d3.csv(file, function (d){...},
function (data) {gdata = data});
gdata2 = data;
}
var gdata1 = {};
var gdata2 = {};
function loadData(file) {
d3.csv(file, function (d){...},
function (data) {gdata = data; displayData(gdata)});
}
很好
谁能解释一下从displayData函数中取出数据数组的最佳/正确方法是什么,以及如何合并两个数据数组(我希望数据是一个映射数组,例如数据[0]是一个映射)。承诺帮助您处理一些回调时有点不愉快的事情。你应该看看 这个小小的d3插件将使它工作: 因此基本上,
d3.promise.csv
取代了loadData
函数
或者按照以下方式进行包装,以始终使用相同的格式化程序:
function loadData(file) {
return d3.promise.csv(file, function (d){...});
}
编辑:
不幸的是,我不能使用任何插件,只有“核心”d3
然后你基本上可以把整个插件复制粘贴到你的代码中,其实没那么多;)
对于这种特殊情况,核心功能可以归结为:
function loadCsv(url){
return new Promise(function(resolve, reject){
d3.csv(url, function (d){...}, function(err, data){
if(err) reject(Error(err));
else resolve(data);
});
});
}
该插件几乎只是以同样的方式包装了更多的方法(如json、xml等),因此更具通用性。您应该看一下源代码。承诺可以帮助您处理回调中有点不愉快的一些事情。你应该看看 这个小小的d3插件将使它工作: 因此基本上,
d3.promise.csv
取代了loadData
函数
或者按照以下方式进行包装,以始终使用相同的格式化程序:
function loadData(file) {
return d3.promise.csv(file, function (d){...});
}
编辑:
不幸的是,我不能使用任何插件,只有“核心”d3
然后你基本上可以把整个插件复制粘贴到你的代码中,其实没那么多;)
对于这种特殊情况,核心功能可以归结为:
function loadCsv(url){
return new Promise(function(resolve, reject){
d3.csv(url, function (d){...}, function(err, data){
if(err) reject(Error(err));
else resolve(data);
});
});
}
该插件几乎只是以同样的方式包装了更多的方法(如json、xml等),因此更具通用性。您应该看看源代码。loadData()
应该进行回调。然后可以在第一个文件的回调中加载第二个文件
function loadData(file, callback) {
d3.csv(file, function(d) { ...}, callback);
}
loadData(file1, function(err1, data1) {
loadData(file2, function(err2, data2) {
// code to combine data1 and data2 and display result
});
});
这样做的缺点是它序列化了文件访问,因此它的性能不如在Thomas的回答中使用promission withPromise.all()
要处理任意数量的文件,可以使用每次递增的变量从数组中提取它们
function loadNextFile(files, i, dataArray) {
if (i >= files.length) {
// merge dataArray and display it
} else {
loadData(files[i], function(err, data) {
dataArray.push(data);
loadNextFile(files, i+1, dataArray);
}
}
}
var filesToLoad = [...];
loadNextFile(filesToLoad, 0, []);
loadData()
应该进行回调。然后可以在第一个文件的回调中加载第二个文件
function loadData(file, callback) {
d3.csv(file, function(d) { ...}, callback);
}
loadData(file1, function(err1, data1) {
loadData(file2, function(err2, data2) {
// code to combine data1 and data2 and display result
});
});
这样做的缺点是它序列化了文件访问,因此它的性能不如在Thomas的回答中使用promission withPromise.all()
要处理任意数量的文件,可以使用每次递增的变量从数组中提取它们
function loadNextFile(files, i, dataArray) {
if (i >= files.length) {
// merge dataArray and display it
} else {
loadData(files[i], function(err, data) {
dataArray.push(data);
loadNextFile(files, i+1, dataArray);
}
}
}
var filesToLoad = [...];
loadNextFile(filesToLoad, 0, []);
管理多个并发请求的状态,然后同步结果可能是一项相当艰巨的工作 管理状态是Promises的主要目的之一,而Promise.all是同步和合并结果 这也是下面代码的主要目的。还有两件事要说:
- 此代码未经测试,可能包含一些错误
- 我已经对这段代码中的几乎所有内容进行了注释,让您了解它的目的/机制是什么,它能做什么,以及如何处理这个怪物的不同用例。这就是为什么这个答案如此漫长的原因
//plain urls, sure
loadCsvFiles('url', function(err, result){ ... })
//an array of urls, it's inital purpose
loadCsvFiles(['url1', 'url2', 'url3'], function(err, results){
console.log(results[0], results[1], results[2]);
});
//urls mapped by property names, I've already mentioned that I prefer that over array indices
loadCsvFiles({
foo: 'file1.csv',
bar: 'file2.csv'
}, function(err, results){
//where `results` resembles the structure of the passed mapping
console.log(results.foo, results.bar);
})
//and through the recursive implementation,
//pretty much every imaginable (non-circular) composition of the examples before
//that's where it gets really crazy/nice
loadCsvFiles({
//mapping a key to a single url (and therefoere result)
data: 'data.csv',
//or one key to an array of results
people: ['people1.csv', 'people2.csv'],
//or a key to a sub-structure
clients: {
jim: 'clients/jim.csv',
//no matter how many levels deep
joe: {
sr: 'clients/joe.sr.csv',
jr: 'clients/joe.jr.csv',
},
//again arrays
harry: [
'clients/harry.part1.csv',
'clients/harry.part2.csv',
//and nested arrays are also possible
[
'clients/harry.part3a.csv',
'clients/harry.part3b.csv'
]
]
},
//of course you can also add objects to Arrays
images: [
{
thumbs: 'thumbs1.csv',
full: 'full1.csv'
},
{
thumbs: 'thumbs2.csv',
full: 'full2.csv'
}
]
}, function(err, results){
//guess what you can access on the results object:
console.log(
results.data,
results.people[0],
results.people[1],
results.clients.jim,
results.clients.joe.sr,
results.clients.joe.jr,
results.clients.harry[0],
results.clients.harry[1],
results.clients.harry[2][0],
results.clients.harry[2][1],
results.images[0].thumbs,
results.images[0].full,
results.images[1].thumbs,
results.images[1].full
)
});
特别是最后一个例子可能对您没有任何意义,因为csv文件的结构很荒谬,但这不是重点。关键是,如何构建数据完全取决于您。只要把它传递给这个文件加载器,它就会处理这个问题
如果您希望同时支持多种文件格式,也可以通过简单的调整:
var loadDifferentFiles = loadFilesFactory(function(url, callback){
if(!url || typeof url !== "string"){
callback(JSON.stringify(url) + ' is no valid url');
return;
}
if(url.endsWith('.csv')){
return d3.csv(url, callback);
}
if(url.endsWith('.json')){
return d3.json(url, callback);
}
//return d3.text(url, callback);
callback('unsupported filetype: ' + JSON.stringify(url));
});
或者像这样的
var loadDifferentFiles = loadFilesFactory(function(value, callback){
if(typeof value !== "string"){
if(value.endsWith('.csv')){
return d3.csv(value, callback);
}
if(value.endsWith('.json')){
return d3.json(value, callback);
}
}
//but in this case, if I don't know how to handle a value
//instead of resolving to an error, just forwarding the passed value to the callback,
//implying that it probably wasn't meant for this code.
callback(null, value);
});
管理多个并发请求的状态,然后同步结果可能是一项相当艰巨的工作 管理状态是Promises的主要目的之一,而Promise.all是同步和合并结果 这也是下面代码的主要目的。还有两件事要说:
- 此代码未经测试,可能包含一些错误
- 我已经对这段代码中的几乎所有内容进行了注释,让您了解它的目的/机制是什么,它能做什么,以及如何处理这个怪物的不同用例。这就是为什么这个答案如此漫长的原因