#javascript #json #d3.js
#javascript #d3.js
Вопрос:
Я пытаюсь загрузить файл GeoJSON и нарисовать некоторые графики, используя его в качестве основы с D3 v5.
Проблема в том, что браузер пропускает все, что включено в d3.json()
вызов. Я попытался вставить точки останова для тестирования, но браузер пропускает их, и я не могу понять, почему.
Фрагмент кода ниже.
d3.json("/trip_animate/tripData.geojson", function(data) {
console.log("It just works"); // This never logs to console.
//...all the rest
}
Код продолжается с начального console.log()
, но я опустил все это, поскольку подозреваю, что проблема связана с самим d3.json
вызовом.
Ответ №1:
Подпись d3.json
изменилась с D3 v4 на v5. Он был перенесен из устаревшего модуля d3-request в новый модуль d3-fetch . Начиная с версии 5, D3 использует API выборки в пользу более старого XMLHttpRequest
и, в свою очередь, использует Promises для обработки этих асинхронных запросов.
Второй аргумент d3.json()
больше не является обратным вызовом, обрабатывающим запрос, а необязательным RequestInit
объектом. d3.json()
теперь вернет обещание, которое вы можете обработать в его .then()
методе.
Таким образом, ваш код становится:
d3.json("/trip_animate/tripData.geojson")
.then(function(data){
// Code from your callback goes here...
});
Обработка ошибок при вызове также изменилась с введением Fetch API. Версии до версии 5 использовали первый параметр обратного вызова, переданный d3.json()
для обработки ошибок:
d3.json(url, function(error, data) {
if (error) throw error;
// Normal handling beyond this point.
});
Начиная с версии D3 v5, обещание, возвращенное с помощью d3.json()
, будет отклонено при возникновении ошибки. Следовательно, могут быть применены ванильные методы JS для обработки этих отклонений:
-
Передайте обработчик отклонения в качестве второго аргумента
.then(onFulfilled, onRejected)
. -
Используется
.catch(onRejected)
для добавления обработчика отклонения к обещанию.
Таким образом, применяя второе решение, ваш код становится
d3.json("/trip_animate/tripData.geojson")
.then(function(data) {
// Code from your callback goes here...
})
.catch(function(error) {
// Do some error handling.
});
Комментарии:
1. @Timmmm, the . затем методу может быть предоставлена дополнительная вторая функция, которая вызывается, если обещание не выполнено:
.then(function(data) {}, function(error) {})
2. @Timmmm В качестве альтернативы вы можете использовать
.catch(function(error) {})
, что в основном эквивалентно предложению Эндрю, но более явно выражено в устной форме.3. Предположим, что мы не можем использовать синтаксис V5 и должны использовать V4. Что мы должны делать тогда?
4. @3xCh1_23 Вы просто используете исходный код, как указано в вопросе.
5. @altocumulus не работает, в этом и был смысл… но нашел обходной путь, которым немного сложнее поделиться…
Ответ №2:
Поскольку ни один из ответов не помог, мне пришлось самостоятельно найти решение, которое работает. Я использую v4 и должен придерживаться его. Проблема заключалась (в моем случае) в том, что d3.json сработал в первый раз, но не сработал во второй или третий раз (с выпадающим списком HTML).
Идея состоит в том, чтобы использовать начальную функцию, а затем просто использовать вторую функцию с
пусть data = ожидает d3.json(«URL»);
вместо
d3.json(«URL», функция (данные) {
Поэтому общий шаблон становится:
async function drawWordcloudGraph() {
let data = await d3.json("URL");
...
}
function initialFunction() {
d3.json("URL", function (data) {
...
});
}
initialFunction();
Я пробовал несколько подходов, и только это сработало. Не уверен, что это можно упростить, пожалуйста, протестируйте самостоятельно.