Прерывание запросов

Zepto.js предоставляет компактный и удобный API для работы с AJAX-запросами, схожий с jQuery, но более лёгкий и оптимизированный для современных браузеров. Одной из важных возможностей при работе с сетевыми запросами является прерывание выполнения запроса, что особенно актуально при динамических интерфейсах, где пользователь может инициировать новые действия до завершения предыдущих запросов.

Возврат объекта jqXHR

При выполнении AJAX-запроса через $.ajax, $.get, $.post или их вариации, возвращается объект jqXHR. Этот объект реализует интерфейс, схожий с XMLHttpRequest, и предоставляет методы для управления запросом, в том числе для его отмены.

Пример создания запроса:

var request = $.ajax({
    url: '/api/data',
    method: 'GET',
    dataType: 'json',
    success: function(data) {
        console.log('Данные получены:', data);
    },
    error: function(xhr, status, error) {
        console.log('Ошибка запроса:', status, error);
    }
});

В этом примере переменная request содержит объект jqXHR, с помощью которого можно отменить запрос до его завершения.

Метод .abort()

Основной способ прерывания запроса — использование метода .abort(). Он останавливает текущий AJAX-запрос и вызывает обработчик error с соответствующим статусом abort.

request.abort();

После вызова .abort():

  • Запрос к серверу немедленно прерывается.
  • Любые обработчики success не выполняются.
  • Обработчик error получает статус abort, что позволяет корректно обработать отмену.

Пример с условием прерывания:

var currentRequest = null;

function fetchData() {
    if (currentRequest) {
        currentRequest.abort();
    }
    currentRequest = $.ajax({
        url: '/api/items',
        method: 'GET',
        dataType: 'json',
        success: function(data) {
            console.log('Данные:', data);
        }
    });
}

// Вызов fetchData несколько раз подряд приведет к отмене предыдущих запросов
fetchData();
fetchData();

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

Особенности прерывания

  1. Асинхронность: .abort() прерывает запрос на уровне сети, но выполнение JavaScript не блокируется.
  2. События: После вызова abort события success не вызываются, а error срабатывает с параметром 'abort'.
  3. Поведение с .then() и промисами: Zepto поддерживает цепочки через .then(). Если запрос был прерван, промис отклоняется, что позволяет обрабатывать отмену в fail или catch.
var req = $.ajax({ url: '/api/data' });

req.then(function(data) {
    console.log('Успех:', data);
}).fail(function(xhr, status) {
    if (status === 'abort') {
        console.log('Запрос был отменен');
    } else {
        console.log('Ошибка:', status);
    }
});

// Отмена запроса через 100 мс
setTimeout(function() {
    req.abort();
}, 100);

Прерывание нескольких запросов

Для интерфейсов с динамической подгрузкой данных часто возникает ситуация, когда необходимо отменять все активные запросы перед отправкой нового. Это реализуется через хранение ссылок на jqXHR-объекты в массиве и последовательный вызов .abort() для всех активных элементов.

var activeRequests = [];

function loadItems(url) {
    // Прерывание всех предыдущих запросов
    activeRequests.forEach(function(req) {
        req.abort();
    });
    activeRequests = [];

    var request = $.ajax({ url: url, dataType: 'json' });
    activeRequests.push(request);

    request.done(function(data) {
        console.log('Данные загружены:', data);
        activeRequests = activeRequests.filter(r => r !== request);
    }).fail(function(xhr, status) {
        if (status !== 'abort') {
            console.log('Ошибка запроса:', status);
        }
        activeRequests = activeRequests.filter(r => r !== request);
    });
}

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

Практические рекомендации

  • Всегда хранить ссылку на объект jqXHR для возможности отмены.
  • Обрабатывать статус 'abort' отдельно, чтобы различать ошибки сети и пользовательскую отмену.
  • Для повторяющихся действий (например, автозагрузка при вводе в поиск) использовать механизм прерывания предыдущих запросов, чтобы улучшить производительность и UX.
  • Не полагаться на автоматическое завершение старых AJAX-запросов при переходе на другую страницу; явное прерывание гарантирует освобождение ресурсов.

Взаимодействие с таймаутами

Zepto позволяет задавать timeout для AJAX-запросов. Если запрос не успевает завершиться в указанный промежуток, он автоматически прерывается, вызывая обработчик error с параметром 'timeout'. В сочетании с .abort() это дает гибкость контроля длительных запросов и предотвращает зависание интерфейса.

var request = $.ajax({
    url: '/api/data',
    timeout: 5000, // 5 секунд
    success: function(data) { console.log(data); },
    error: function(xhr, status) {
        if (status === 'timeout') console.log('Превышено время ожидания');
    }
});

Прерывание запросов в Zepto обеспечивает эффективное управление асинхронными операциями, уменьшает нагрузку на сервер и повышает отзывчивость интерфейсов. Контроль через .abort(), хранение jqXHR-объектов и обработка статусов 'abort' и 'timeout' — ключевые элементы грамотного построения AJAX-функциональности.