JQuery AJAX-запрос, дождитесь завершения последнего запроса - PullRequest
8 голосов
/ 05 января 2010

У меня есть текстовое поле, в котором каждый раз, когда пользователь вводит букву, я выполняю поиск по запросу ajax и показываю результат «вживую» для пользователя. Часто, когда пользователь печатает буквы, для выполнения запроса требуется больше времени, чем для ввода новой буквы, следовательно, новый запрос выполняется до того, как закончится первый. Было бы намного лучше, если бы первый мог закончиться, прежде чем я сделаю следующий запрос. Есть ли хороший способ сделать новый запрос, только если последний запрос закончился?

Это мой код jquery:

$("#MyTextBox").change(function() {
    if (this.value.length > 2) {
        $.ajax({
            type: "GET",
            url: "http://www.domain.com/Service.svc/Search?keyword=" + this.value,
            dataType: "json",
            success: function(data) {
                //here I have some code that shows the result for the user
            }
        });
    }
});

Ответы [ 5 ]

10 голосов
/ 05 января 2010

Вы можете создать логическое значение, которое будет содержать значение true или false в зависимости от того, есть ли уже запрос. Установите его в true, когда вы запускаете запрос, и установите его обратно в false в вашей функции обратного вызова.

var request_in_process = false;
$("#MyTextBox").change(function() {
    if (this.value.length > 2 && !request_in_process) {
        request_in_process = true;
        $.ajax({
            type: "GET",
            url: "http://www.domain.com/Service.svc/Search?keyword=" + this.value,
            dataType: "json",
            success: function(data) {
                request_in_process = false;
                //here I have some code that shows the result for the user
            }
        });
    }
});
8 голосов
/ 05 января 2010

Вы можете прервать запрос AJAX. Отслеживайте запрос как переменную и прерывайте его перед повторной инициацией запроса.

var request = $.ajax({ ... });
request.abort();

Это имеет дополнительное преимущество, заключающееся в большей отзывчивости к пользовательскому вводу. Если пользователь набрал что-то большее с момента инициации первого запроса, он, вероятно, больше не заботится о первом наборе результатов. Прерывание и повторное создание запроса AJAX означает, что пользователь получает лучший набор результатов обратно.

0 голосов
/ 06 ноября 2013

Вот немного более надежная реализация. По сути, мы сохраняем объект ajax (т.е. объект обещания), чтобы закрыть его, чтобы последующие вызовы могли на него посмотреть. Если при следующих вызовах обнаруживается, что статус запроса находится в состоянии ожидания, он будет добавлять обратные вызовы к этому ожидающему запросу, а не генерировать новый запрос. jQuery будет запускать все обратные вызовы в той же последовательности, в которой они были добавлены. Однако есть вероятность, что один и тот же вызывающий абонент пытается создать запрос снова и снова. Чтобы защититься от этого, я добавил параметр callerId. Если тот же абонент сделал запрос еще раз, пока предыдущий запрос все еще находился на рассмотрении, мы просто игнорируем этот запрос. Для полноты я также добавил cachedValues. Так что если ajax-запрос уже сделан, мы не делаем его снова.

var ajaxRequestor = function ($) {
    "use strict";

    //privates
    var cahedValues = {};
    var currentAjaxRequest, callers;

    //public interface
    return {
        getData: function (callerId, onGet, onFail, forceRefresh) {
            if (forceRefresh || !cahedValues.myData) {

                //If there is a pending request, don't start new one
                if (!currentAjaxRequest || currentAjaxRequest.state() != "pending") {
                    currentAjaxRequest = $.getJSON("data/MyData.json");
                    callers = {};   //list of callers waiting for request
                }

                //if this caller is not in the list, add it and queue up its callbacks to existing request
                if (!callers[callerId]) {   
                    callers.callerId = callerId;

                    currentAjaxRequest.done(function (data, textStatus) {
                        cahedValues.myData = data;
                        onGet(data);
                    });

                    currentAjaxRequest.fail(function (jqxhr, textStatus, error) {
                        if (!!onFail) {
                            onFail(error);
                        }
                        else throw error;
                    });
                }
            }
            else {
                onGet(cahedValues.myData);
            }
        },

        invalidateMyData: function () {
            delete cahedValues.myData;
        }
    };
})($);
0 голосов
/ 05 января 2010

Как уже упоминалось в ceejayoz, вам следует прервать предыдущий запрос. (Ожидание запроса приведет пользователей в бешенство, если они не смогут печатать так, как хотят. А предпочтение более старых запросов более новым делает результаты устаревшими.) А что насчет:

var request = null;
//...       
$("#MyTextBox").change(function() {
    if (this.value.length > 2) {
        if (request && request.abort)
            request.abort();
        request = $.ajax({
            type: "GET",
            url: "http://www.domain.com/Service.svc/Search?keyword=" + this.value,
            dataType: "json",
            success: function(data) {
            //here I have some code that shows the result for the user
            request = null;                
        });
    }             
});
0 голосов
/ 05 января 2010

Вы можете использовать ajaxComplete , чтобы вы знали, когда запрос завершился, прежде чем делать новый запрос.

Вы можете объединить это с bind / unbind, так что событие изменения добавляется один раз вручную, затем не связывается при запуске запроса ajax и восстанавливается после завершения запроса ajax.

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