При работе с асинхронными источниками данных компонент выбора становится зависимым от сетевых задержек и времени ответа API. В подобных условиях индикация загрузки выполняет не декоративную, а функциональную роль: она сигнализирует о состоянии запроса, предотвращает повторные действия пользователя и формирует предсказуемое поведение интерфейса.
Tom Select предоставляет встроенный механизм управления состоянием загрузки, который интегрирован в цикл получения данных, рендеринга опций и обработки пользовательского ввода.
В основе асинхронной модели лежит функция
load(query, callback), которая вызывается при необходимости
получения данных извне. В момент запуска запроса компонент автоматически
переводится в состояние загрузки.
Ключевые особенности:
loadingМеханизм загрузки не требует ручного переключения флагов в базовой конфигурации, однако предоставляет точки расширения для кастомизации поведения.
Во время выполнения запроса основной контейнер компонента получает CSS-класс:
loading — активная загрузка данныхЭтот класс применяется к корневому элементу селекта и может быть использован для стилизации индикаторов.
Пример типичной структуры DOM в момент загрузки:
loadingИспользование этого состояния позволяет:
Основной точкой интеграции является функция load,
определяемая при инициализации компонента:
new TomSelect("#select", {
load: function(query, callback) {
fetch(`/api/items?q=${encodeURIComponent(query)}`)
.then(response => response.json())
.then(data => callback(data.items))
.catch(() => callback([]));
}
});
Параметры функции:
query — текущий ввод пользователяcallback — функция завершения загрузкиОсобенности поведения:
callback([]) завершает состояние загрузки без
результатовload игнорируется при активном
запросеcallback блокирует интерфейсДля предотвращения избыточных обращений к серверу используется параметр:
loadThrottleОн определяет минимальный интервал между запросами в миллисекундах.
Пример конфигурации:
new TomSelect("#select", {
loadThrottle: 300,
load: function(query, callback) {
api.search(query).then(callback);
}
});
Поведение:
В некоторых сценариях требуется загрузка данных до ввода пользователя. Для этого используется параметр:
preloadВозможные значения:
true — загрузка при инициализации"focus" — загрузка при фокусе на полеfalse — отключеноПредзагрузка влияет на начальное состояние компонента и может комбинироваться с кешированием.
Встроенный индикатор может быть заменён через систему рендеринга.
Пример кастомного отображения:
new TomSelect("#select", {
load: function(query, callback) {
api.search(query).then(callback);
},
render: {
loading: function() {
return `<div class="ts-loading-indicator">
<span class="spinner"></span>
</div>`;
}
}
});
Особенности кастомного рендера:
При работе с серверными источниками важно учитывать структуру данных и задержки сети.
Типовая схема:
loadThrottleloadloadingloadingДополнительно могут использоваться:
maxOptions)Ошибки сетевых запросов не должны приводить к зависанию интерфейса.
Обязательное правило — завершение callback даже при
ошибке.
Пример обработки:
load: function(query, callback) {
fetch(`/api/items?q=${query}`)
.then(r => r.json())
.then(data => callback(data.items))
.catch(err => {
console.error(err);
callback([]);
});
}
Поведение при ошибке:
loading снимается автоматическиПри высокой скорости ввода возможны ситуации, когда ответы приходят в неправильном порядке. Для предотвращения этого применяются стратегии:
query перед применением результатаПример защиты:
let lastQuery = "";
load: function(query, callback) {
lastQuery = query;
fetch(`/api?q=${query}`)
.then(r => r.json())
.then(data => {
if (query === lastQuery) {
callback(data.items);
}
});
}
Для уменьшения нагрузки на сервер используется кэширование запросов.
Подходы:
queryПример:
const cache = new Map();
load: function(query, callback) {
if (cache.has(query)) {
callback(cache.get(query));
return;
}
fetch(`/api?q=${query}`)
.then(r => r.json())
.then(data => {
cache.set(query, data.items);
callback(data.items);
});
}
Во время активной загрузки компонент может:
Поведение зависит от конфигурации и реализации load, но
базовый механизм гарантирует согласованность UI-состояния.
Стандартный класс loading позволяет полностью
контролировать внешний вид:
.ts-wrapper.loading {
opacity: 0.8;
}
.ts-wrapper.loading .ts-dropdown {
pointer-events: none;
}
Дополнительные техники:
Для интерфейсов с высокой частотой ввода критично снижать нагрузку на сеть и визуально стабилизировать список.
Используются подходы:
loadThrottleКомбинация этих методов снижает задержки восприятия и уменьшает визуальные скачки интерфейса.
Состояние загрузки тесно связано с внутренним жизненным циклом:
Такая модель обеспечивает предсказуемость поведения при динамическом монтировании и размонтировании элементов интерфейса.