Код в обратном вызове d3.json() не выполняется

#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 для обработки этих отклонений:

  1. Передайте обработчик отклонения в качестве второго аргумента .then(onFulfilled, onRejected) .

  2. Используется .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();
  

Я пробовал несколько подходов, и только это сработало. Не уверен, что это можно упростить, пожалуйста, протестируйте самостоятельно.