Если пользователь быстро переключается между табами (например, "фильмы" и "сериалы"), и каждый таб запускает API-запрос, то может возникнуть ситуация, когда ответы приходят не в том порядке, в котором были сделаны запросы. В итоге UI может отобразить данные не того таба, который сейчас активен.
Как избежать ситуации, когда при поиске пользователей после быстрого изменения запроса отображаются результаты предыдущего запроса, хотя все запросы завершились успешно?
В итоге UI может отобразить данные не того таба, который сейчас активен.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Если пользователь быстро переключается между табами (например, "фильмы" и "сериалы"), и каждый таб запускает API-запрос, то может возникнуть ситуация, когда ответы приходят не в том порядке, в котором были сделаны запросы. В итоге UI может отобразить данные не того таба, который сейчас активен.
Проблемы:
- Переключение вызывает множественные параллельные запросы.
- Ответы приходят асинхронно и могут обновить состояние после переключения.
Как пофиксить:
- Отмена предыдущих запросов — при переключении таба отменять все незавершённые запросы, чтобы их результаты не применялись.
- Использование токенов или счётчиков запросов — при каждом запросе генерировать уникальный идентификатор, и обновлять состояние только если ответ соответствует последнему запросу.
- Дебаунсинг переключения — задерживать отправку запроса, чтобы избежать лишних вызовов при быстром переключении.
Пример на JavaScript с использованием AbortController для отмены запросов:
let currentController = null;
function fetchDataForTab(tab) {
if (currentController) {
currentController.abort(); // отменяем предыдущий запрос
}
currentController = new AbortController();
fetch(`/api/${tab}`, { signal: currentController.signal })
.then(response => response.json())
.then(data => {
// обновляем UI только если запрос не был отменён
renderData(tab, data);
})
.catch(err => {
if (err.name === 'AbortError') {
// запрос отменён, ничего не делаем
} else {
console.error(err);
}
});
}