Обработка ошибок и исключений

При работе с Turf.js большинство ошибок возникает не в самой библиотеке, а на уровне входных геоданных и предположений о структуре GeoJSON. Turf.js строго следует спецификации GeoJSON, поэтому любое отклонение от формата приводит к выбросам исключений или некорректным результатам вычислений.

Некорректный GeoJSON как основная причина сбоев

Turf.js ожидает строго валидные объекты GeoJSON. Нарушение структуры приводит к ошибкам вида TypeError, Error: Invalid GeoJSON object или внутренним исключениям функций обработки.

К типичным проблемам относятся:

  • отсутствие поля type
  • отсутствие или повреждение coordinates
  • неверная вложенность координат
  • использование строк вместо чисел
  • перепутанный порядок координат (широта/долгота)

Пример некорректного объекта:

const point = {
  type: "Point",
  coordinates: ["55.75", "37.61"]
};

Правильный вариант:

const point = {
  type: "Point",
  coordinates: [37.61, 55.75]
};

Даже незначительное отклонение, например строковые координаты, может привести к NaN внутри геометрических операций.


Ошибки типов геометрий

Turf.js строго различает типы геометрий. Передача неподходящего типа приводит к логическим или runtime-ошибкам.

Например, функция turf.length ожидает LineString или MultiLineString. Передача Point не имеет геометрического смысла:

turf.length(point); // ошибка или бессмысленный результат

Для предотвращения подобных ситуаций используется проверка geometry.type:

function assertLineString(feature) {
  if (!feature || feature.geometry?.type !== "LineString") {
    throw new Error("Ожидается LineString");
  }
}

Обработка исключений при вызове Turf.js

Большинство функций Turf.js не возвращают код ошибки — они выбрасывают исключения. Поэтому стандартный механизм обработки строится на try...catch.

Базовая структура обработки

import * as turf from "@turf/turf";

try {
  const line = turf.lineString([[0, 0], [10, 10]]);
  const result = turf.length(line);
} catch (err) {
  console.error("Ошибка геообработки:", err.message);
}

Такой подход критически важен при работе с пользовательскими данными, API или внешними источниками GeoJSON.


Ловля ошибок в цепочках операций

Turf.js часто используется в виде цепочек трансформаций:

const buffered = turf.buffer(
  turf.cleanCoords(
    turf.lineString(coords)
  ),
  5
);

При такой композиции ошибка может возникнуть на любом этапе. Для точной диагностики используется разбиение цепочки:

let line;

try {
  line = turf.lineString(coords);
} catch (e) {
  throw new Error("Ошибка создания LineString");
}

let cleaned;

try {
  cleaned = turf.cleanCoords(line);
} catch (e) {
  throw new Error("Ошибка очистки координат");
}

Такой подход упрощает локализацию проблем в геометрии.


Проверка валидности геометрий

Turf.js не всегда выполняет автоматическую валидацию топологии. Поэтому некорректные геометрии могут проходить через функции и давать неожиданные результаты.

Самопересечения и некорректные полигоны

Полигон с самопересечением может приводить к некорректным площадям и буферам.

Пример проблемного полигона:

const polygon = turf.polygon([[
  [0, 0],
  [10, 10],
  [0, 10],
  [10, 0],
  [0, 0]
]]);

Такая геометрия пересекает сама себя.

Для выявления используются дополнительные проверки, например:

  • @turf/boolean-valid (в некоторых сборках)
  • @turf/kinks
  • геометрические эвристики

Пример:

import booleanValid from "@turf/boolean-valid";

if (!booleanValid(polygon)) {
  throw new Error("Некорректный полигон");
}

Проверка координатных диапазонов

Одной из частых причин скрытых ошибок является выход координат за допустимые пределы:

  • долгота: от -180 до 180
  • широта: от -90 до 90
function validateCoord([lng, lat]) {
  if (lng < -180 || lng > 180) {
    throw new Error("Некорректная долгота");
  }
  if (lat < -90 || lat > 90) {
    throw new Error("Некорректная широта");
  }
}

Ошибки, связанные с единицами измерения

Turf.js работает с географическими координатами и различными единицами измерения. Несоответствие единиц — частый источник логических ошибок.

Радианы и градусы

Некоторые внутренние расчёты используют радианы, но входные данные всегда задаются в градусах.

Ошибка возникает, когда разработчик вручную передаёт радианы:

// ошибка: координаты в радианах
const point = turf.point([1.2, 0.8]);

Правильный подход — всегда использовать градусы.


Метры и километры в буферах

Функция turf.buffer принимает расстояние и единицы измерения:

turf.buffer(point, 5, { units: "kilometers" });

Ошибка:

turf.buffer(point, 5000); // неоднозначно: метры или километры

Явное указание единиц снижает риск неверной интерпретации.


Защита от NaN и числовых переполнений

Геометрические операции могут приводить к NaN, если входные данные содержат:

  • undefined
  • null
  • строки
  • пустые массивы
  • некорректные преобразования

Пример защиты входных данных

function sanitizeCoords(coords) {
  return coords.filter(c =>
    Array.isArray(c) &&
    Number.isFinite(c[0]) &&
    Number.isFinite(c[1])
  );
}

Проверка результата операций

const area = turf.area(polygon);

if (!Number.isFinite(area)) {
  throw new Error("Ошибка вычисления площади");
}

Обработка ошибок при работе с внешними источниками данных

Наиболее нестабильный сценарий — загрузка GeoJSON из API, файлов или пользовательского ввода.

Типичный поток обработки

async function loadGeoJSON(url) {
  const res = await fetch(url);

  if (!res.ok) {
    throw new Error("Ошибка загрузки данных");
  }

  const data = await res.json();

  if (!data || data.type !== "FeatureCollection") {
    throw new Error("Неверный формат GeoJSON");
  }

  return data;
}

После загрузки данные дополнительно проходят проверку перед передачей в Turf.js.


Ошибки в работе с CRS и проекциями

Turf.js работает в WGS84 (EPSG:4326). Использование данных в других системах координат без преобразования приводит к критическим искажениям.

Типичный сбой

  • координаты в Web Mercator (EPSG:3857)
  • расчет расстояний как будто это градусы

Результат — некорректные дистанции и площади.

Защитная стратегия

function assertWGS84(feature) {
  const [lng, lat] = feature.geometry.coordinates;

  if (Math.abs(lng) > 180 || Math.abs(lat) > 90) {
    throw new Error("Ожидаются координаты WGS84");
  }
}

Контроль ошибок в геометрических преобразованиях

Некоторые операции Turf.js изменяют структуру геометрии:

  • turf.buffer
  • turf.dissolve
  • turf.intersect
  • turf.union

Каждая из них может вернуть null при отсутствии результата пересечения.

Пример обработки null

const result = turf.intersect(poly1, poly2);

if (!result) {
  throw new Error("Пересечение отсутствует");
}

Игнорирование этого поведения приводит к ошибкам при последующих операциях.


Стратегии устойчивой архитектуры обработки ошибок

Изоляция геоопераций

Геометрические расчёты целесообразно выносить в отдельный слой:

function safeBuffer(feature, distance) {
  try {
    return turf.buffer(feature, distance, { units: "meters" });
  } catch (e) {
    return null;
  }
}

Логирование контекста ошибки

При геообработке важно сохранять входные данные:

try {
  const result = turf.area(polygon);
} catch (e) {
  console.error("Ошибка вычисления площади", {
    error: e.message,
    feature: polygon
  });
}

Защита на уровне типов (TypeScript)

При использовании TypeScript часть ошибок устраняется на этапе компиляции:

import { Feature, Polygon } from "@turf/helpers";

function process(poly: Feature<Polygon>) {
  return turf.area(poly);
}

Однако даже строгая типизация не защищает от некорректных координат.


Обработка каскадных ошибок в сложных геоалгоритмах

При построении сложных систем (маршрутизация, кластеризация, анализ зон покрытия) ошибка в одной геометрии может распространяться по всей цепочке вычислений.

Типичная стратегия:

  • валидация входных данных
  • локальная обработка ошибок
  • пропуск некорректных объектов
  • агрегация результатов с фильтрацией null
const results = features
  .map(f => {
    try {
      return turf.buffer(f, 1);
    } catch {
      return null;
    }
  })
  .filter(Boolean);

Поведение ошибок в разных средах выполнения

Browser

Ошибки чаще проявляются как Uncaught Error, если отсутствует глобальный обработчик:

window.addEventListener("error", (e) => {
  console.error("Geo error:", e.message);
});

Node.js

В Node.js возможна интеграция с централизованным логированием:

process.on("uncaughtException", (err) => {
  console.error("Критическая геоошибка:", err);
});

Диагностика ошибок через декомпозицию геометрий

При сложных полигонах полезно упрощать геометрию:

  • удаление лишних точек
  • проверка сегментов
  • пошаговая визуализация
const simplified = turf.simplify(polygon, {
  tolerance: 0.01,
  highQuality: true
});

Ошибки часто исчезают после упрощения, что указывает на проблему исходной топологии.


Контроль предельных случаев

Критические edge cases:

  • пустые FeatureCollection
  • полигоны с одной точкой
  • линии с одинаковыми координатами
  • полностью вырожденные геометрии
function isDegenerateLine(line) {
  return line.geometry.coordinates.length < 2;
}

Такие проверки предотвращают большинство runtime-ошибок Turf.js.