JQuery UI автозаполнения: как отменить медленный AJAX-запрос после потери ввода текста - PullRequest
11 голосов
/ 13 октября 2011

Я использую поле автозаполнения пользовательского интерфейса JQuery, связанное с поиском ajax, которое иногда может быть довольно медленным.Иногда пользователь отходит от поля ввода текста после запроса ajax, но до возврата вызова ajax.Когда это происходит, всплывающее окно автозаполнения появляется, даже несмотря на то, что текстовый ввод больше не имеет фокуса, и единственный способ отклонить это всплывающее окно - выбрать элемент (а не вкладывать его в другое поле).это jquery ui demo демонстрирует то же поведение (например, введите «ariz» в текстовое поле, подождите, пока не появится анимация «поиска», а затем выведите его из поля, прежде чем он вернет результаты).

Одно из решений, которое работает (но выглядит как хак), - это проверить в обратном вызове ajax success, чтобы увидеть, имеет ли текстовое поле все еще фокус, и если не вызывать response () с пустым списком, например:

        $( "#city" ).autocomplete({
        var elem = this.element;
        source: function( request, response ) {
            $.ajax({
                url: "http://ws.geonames.org/searchJSON",
                data: {name_startsWith: request.term},
                success: function( data ) {
                    if(!$(elem).is(':focus') {
                        response({});
                        return;
                    }
                    response( $.map( data.geonames, function( item ) {
                        return {
                            label: item.name + (item.adminName1 ? ", " + item.adminName1 : "") + ", " + item.countryName,
                            value: item.name
                        }
                    }));
                }
            });
        }
    });

Есть ли более изящное решение?В идеале я бы хотел отменить запрос ajax, как только пользователь покинет поле ввода текста.

1 Ответ

14 голосов
/ 13 октября 2011

$.ajax возвращает объект jqXHR, и этот объект предоставляет метод abort базового объекта XMLHttpRequest.Итак, вам просто нужно спрятать jqXHR и прервать запрос в нужное время.Возможно, что-то вроде этого:

source: function(request, response) {
    var $this = $(this);
    var $element = $(this.element);
    var jqXHR = $element.data('jqXHR');
    if(jqXHR)
        jqXHR.abort();
    $element.data('jqXHR', $.ajax({
        // ...
        complete: function() {
            // This callback is called when the request completes
            // regardless of success or failure.
            $this.removeData('jqXHR');
            // And dismiss the search animation.
            response({});
        }
    });
}

А затем вам понадобится кое-что на #city:

$('#city').blur(function() {
    var $this = $(this);
    var jqXHR = $(this).data('jqXHR');
    if(jqXHR)
        jqXHR.abort();
    $this.removeData('jqXHR');
});

Иногда при обычной работе автозаполнения возникает короткое размытие / фокусировка, ноэто происходит только тогда, когда кто-то выбирает что-то из списка;когда это происходит, запрос $.ajax не должен выполняться, поэтому нам не нужно об этом беспокоиться.Если я ошибаюсь, вы можете обойти это, используя таймер внутри обработчика blur и отменив таймер в обратном вызове focus (вы можете сохранить идентификатор таймера и в другом слоте .data()).

Я не проверял это, но я уверен, что это будет работать.

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