Обновлено: согласно приведенному ниже ответу и для дальнейшего использования, исходным источником является Хороплет мира от Palawire.
Я пытаюсь повторно использовать кучу примеров Майка, переключая источник данных с CSV на JSON.
Исходный источник данных загружается из файла CSV следующим образом:
// Load external data and boot
d3.queue()
.defer(d3.json, "http://enjalot.github.io/wwsd/data/world/world-110m.geojson")
.defer(d3.csv, "mooc-countries.csv", function(d) { data.set(d.code, +d.total); })
.await(ready);
function ready(error, topo) {
if (error) throw error;
// Draw the map
svg.append("g")
.attr("class", "countries")
.selectAll("path")
.data(topo.features)
.enter().append("path")
.attr("fill", function (d){
// Pull data for this country
d.total = data.get(d.id) || 0;
// Set the color
return colorScale(d.total);
})
.attr("d", path);
}
Но я пытаюсь изменить второй .defer для получения данных из файла JSON, пока я понял, что он должен быть близок к этому:
.defer(d3.json, "data.json", function(error, data) {
data.forEach(function(d) {
return {
d.code,
d.total;
};
});
})
Источник JSON:
[
{
"name" : "Burkina Faso",
"total" : 5,
"percent" : 0.3,
"code" : "BFA"
},
{
"name" : "Democratic Republic of the Congo",
"total" : 4,
"percent" : 0.3,
"code" : "COD"
},
{
"name" : "Haiti",
"total" : 8,
"percent" : 0.3,
"code" : "HTI"
}
]



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Вероятно, вы ищете возврат нового массива с выбранными вами ключами. Возврат внутри вашего forEach - текущая проблема. Возможно, вы хотите вернуть это
map преобразует массив объектов в другой формат, затем вы возвращаетесь к своей функции отсрочки.
.defer(d3.json, "data.json", function(error, data) {
return data.map(function(d) {
return {
id: d.code,
total: d.total;
};
});
})
Вы не включили какую-либо ссылку на исходный блок, но, погуглив, я думаю, вы имеете в виду Хороплет мира ру-палевайр. Перенос этого для использования d3.json() требует некоторых дополнительных шагов.
Существует глобальная переменная data, которая представляет собой d3.map:
var data = d3.map();
Этот словарь содержит сопоставления code → total, извлеченные из CSV и используемые в дальнейшем при определении fill. Если вы хотите сохранить общую структуру кода, вам нужно заполнить те же значения из ввода JSON. Это подводит нас прямо к следующему вопросу.
В исходном коде карта заполняется функцией в этой строке:
.defer(d3.csv, "mooc-countries.csv", function(d) { data.set(d.code, +d.total); })
Однако важно понимать, что эта функция нет является обратным вызовом, обрабатывающим полученный набор данных; этот обратный вызов скрыт и неявно обеспечивается очередью. Вместо этого это функция преобразование строки, которая выполняется для каждой строки CSV. Это использует .set() для помещения каждой строки в карту. Придерживаясь соглашения об именах D3, параметр функции обозначается как d, относящийся к одному элементу данных, а не ко всему набору данных.
d3.json(), с другой стороны, не имеет функции преобразования строк, потому что данные JSON по своей сути иерархичны, а не основаны на строках, как CSV. Вы можете поместить эту логику в обратный вызов, переданный на .await():
d3.queue()
.defer(d3.json, "http://enjalot.github.io/wwsd/data/world/world-110m.geojson")
.defer(d3.json, "data.json") // No callback, just loading.
.await(ready);
function ready(error, topo, json) {
if (error) throw error;
var data = d3.map(); // Can be moved here, no need to pollute the global scope.
json.forEach(function(d) { data.set(d.code, +d.total); }); // Populate the map.
// ...business as usual
}
Для остального кода еще есть много возможностей для улучшения (например, переход на D3 v5 и ES6), но вышеупомянутые манипуляции, вероятно, являются наименее навязчивым способом и сохранят большую часть исходного кода нетронутым.
Какой у Вас вопрос? Выдает ошибку? Если да, то в чем ошибка?