Обработка ошибок

SortableJS — это высокоэффективная библиотека для создания интерактивных списков с поддержкой перетаскивания элементов. Как и любая динамическая библиотека, она требует тщательной обработки ошибок, чтобы приложение оставалось стабильным и предсказуемым при нестандартных сценариях взаимодействия пользователя с элементами списка.


Виды возможных ошибок

Ошибки при работе с SortableJS можно разделить на несколько категорий:

  1. Ошибки инициализации

    • Попытка инициализировать Sortable на несуществующем DOM-элементе.
    • Передача некорректных параметров конфигурации.
    • Повторная инициализация одного и того же элемента без предварительного разрушения существующего экземпляра.
  2. Ошибки взаимодействия

    • Перетаскивание элемента в недопустимую область.
    • Несоответствие типов элементов в группах, если используется параметр group.
    • Нарушение ограничения filter или disabled, когда пользователь пытается перетащить элемент, который не должен быть перетаскиваемым.
  3. Ошибки события

    • Некорректная обработка событий onEnd, onAdd, onUpdate и других.
    • Ошибки в колбэках, приводящие к остановке скрипта.

Инициализация с защитой от ошибок

Инициализация SortableJS должна сопровождаться проверкой существования целевого элемента и корректности конфигурации:

const container = document.querySelector('#sortable-list');

if (container) {
    try {
        const sortable = new Sortable(container, {
            animation: 150,
            handle: '.handle',
            ghostClass: 'sortable-ghost',
            onEnd: function (evt) {
                console.log(`Элемент перемещён с позиции ${evt.oldIndex} на позицию ${evt.newIndex}`);
            }
        });
    } catch (error) {
        console.error('Ошибка при инициализации Sortable:', error);
    }
} else {
    console.warn('Элемент для Sortable не найден');
}

Ключевой момент: использование try/catch предотвращает падение приложения при некорректной конфигурации или DOM-ошибках.


Валидация параметров

SortbaleJS допускает множество настроек: animation, group, handle, filter, disabled, store и другие. Ошибки часто возникают при передаче значений неправильного типа или некорректных объектов. Для предотвращения таких ошибок полезно выполнять валидацию:

function validateSortableOptions(options) {
    if (typeof options.animation !== 'number' || options.animation < 0) {
        throw new Error('Параметр animation должен быть положительным числом');
    }
    if (options.group && typeof options.group !== 'string' && typeof options.group !== 'object') {
        throw new Error('Параметр group должен быть строкой или объектом');
    }
    if (options.handle && typeof options.handle !== 'string') {
        throw new Error('Параметр handle должен быть строковым селектором');
    }
    return true;
}

try {
    const options = { animation: 150, handle: '.handle' };
    validateSortableOptions(options);
    const sortable = new Sortable(document.querySelector('#sortable-list'), options);
} catch (error) {
    console.error('Ошибка конфигурации Sortable:', error);
}

Обработка ошибок событий

События SortableJS позволяют реагировать на действия пользователя, но ошибки в колбэках могут нарушить логику приложения. Для безопасной работы рекомендуется оборачивать обработчики в блоки try/catch:

const sortable = new Sortable(container, {
    onEnd: function(evt) {
        try {
            if (!evt.item.dataset.id) {
                throw new Error('Элемент не имеет идентификатора');
            }
            updateOrder(evt.item.dataset.id, evt.newIndex);
        } catch (error) {
            console.error('Ошибка в обработчике события onEnd:', error);
        }
    }
});

Такой подход позволяет логировать ошибки без прерывания работы интерфейса и предотвращает неконтролируемое поведение списка.


Работа с асинхронными операциями

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

async function updateOrder(id, newIndex) {
    try {
        const response = await fetch('/api/update-order', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ id, newIndex })
        });
        if (!response.ok) throw new Error(`Ошибка сервера: ${response.status}`);
    } catch (error) {
        console.error('Не удалось сохранить порядок элементов:', error);
    }
}

Важный нюанс: событие onEnd уже произошло, поэтому важно предусмотреть откат состояния интерфейса при ошибке сохранения.


Логирование и мониторинг

Для больших приложений рекомендуется вести централизованное логирование всех ошибок SortableJS. Можно создавать универсальные функции обработки ошибок, которые записывают данные в консоль и отправляют их на сервер:

function logSortableError(context, error) {
    console.error(`[SortableJS][${context}]`, error);
    fetch('/api/log-error', {
        method: 'POST',
        body: JSON.stringify({ context, message: error.message, stack: error.stack }),
        headers: { 'Content-Type': 'application/json' }
    }).catch(console.error);
}

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


Рекомендации по предотвращению ошибок

  • Проверять наличие DOM-элементов перед инициализацией.
  • Валидировать параметры конфигурации.
  • Оборачивать колбэки событий в try/catch.
  • Обрабатывать ошибки асинхронных операций при работе с сервером.
  • Использовать централизованное логирование для диагностики и мониторинга.

Эти меры создают устойчивую архитектуру при работе с SortableJS, позволяя спискам оставаться интерактивными и предсказуемыми даже при непредвиденных действиях пользователей.