Как отменить / отменить запрос jQuery AJAX?

214

У меня есть запрос AJAX, который будет выполняться каждые 5 секунд. Но проблема перед запросом AJAX, если предыдущий запрос не завершен, я должен прервать этот запрос и сделать новый запрос.

Мой код выглядит примерно так: как решить эту проблему?

$(document).ready(
    var fn = function(){
        $.ajax({
            url: 'ajax/progress.ftl',
            success: function(data) {
                //do something
            }
        });
    };

    var interval = setInterval(fn, 500);
);
Теги:

9 ответов

326
Лучший ответ

Метод jQuery ajax возвращает объект XMLHttpRequest. Вы можете использовать этот объект для отмены запроса.

XMLHttpRequest имеет метод abort, который отменяет запрос, но если запрос уже отправлен на сервер, тогда сервер будет обрабатывать запрос даже если мы отменим запрос, но клиент не будет ждать/обрабатывать ответ.

Объект xhr также содержит readyState, который содержит состояние запроса (UNSENT-0, OPENED-1, HEADERS_RECEIVED-2, LOADING-3 и Совершено-4). мы можем использовать это, чтобы проверить, был ли предыдущий запрос завершен.

$(document).ready(
    var xhr;

    var fn = function(){
        if(xhr && xhr.readyState != 4){
            xhr.abort();
        }
        xhr = $.ajax({
            url: 'ajax/progress.ftl',
            success: function(data) {
                //do something
            }
        });
    };

    var interval = setInterval(fn, 500);
);
  • 3
    @rtpHarry Спасибо за обновление по сравнению с jQuery 1.5
  • 60
    @romkyns Различия - это свойство readystate выше и readyState ниже, символ s заглавными в jQuery 1.5
Показать ещё 5 комментариев
9

Просто используйте ajax.abort(), например, вы можете прервать любой ожидающий запрос ajax перед отправкой другого, подобного этому

//check for existing ajax request
if(ajax){ 
 ajax.abort();
 }
//then you make another ajax request
$.ajax(
 //your code here
  );
4

Я знаю, что это может быть немного поздно, но у меня возникают аналогичные проблемы, когда вызов метода прерывания действительно не прервал запрос. вместо этого браузер все еще ожидал ответа, который он никогда не использует. этот код разрешил эту проблему.

 try {
        xhr.onreadystatechange = null;
        xhr.abort();
} catch (e) {}
3

Зачем вам отменять запрос?

Если каждый запрос занимает более пяти секунд, что произойдет?

Вы не должны прерывать запрос, если параметр, передаваемый с запросом, не изменяется. например: - запрос на получение данных уведомления. В таких ситуациях приятным подходом является то, что задать новый запрос только после завершения предыдущего запроса Ajax.

$(document).ready(

    var fn = function(){

        $.ajax({
            url: 'ajax/progress.ftl',
            success: function(data) {
                //do something
            },

            complete: function(){setTimeout(fn, 500);}
        });
    };

     var interval = setTimeout(fn, 500);

);
  • 4
    Это плохая идея. При запуске нового вызова вы не хотите, чтобы завершенное событие было запущено по сравнению с предыдущим вызовом. При таком подходе вы можете получить очень странные результаты.
0

Вы можете использовать jquery-validate.js. Ниже приведен фрагмент кода из jquery-validate.js.

// ajax mode: abort
// usage: $.ajax({ mode: "abort"[, port: "uniqueport"]});
// if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort()

var pendingRequests = {},
    ajax;
// Use a prefilter if available (1.5+)
if ( $.ajaxPrefilter ) {
    $.ajaxPrefilter(function( settings, _, xhr ) {
        var port = settings.port;
        if ( settings.mode === "abort" ) {
            if ( pendingRequests[port] ) {
                pendingRequests[port].abort();
            }
            pendingRequests[port] = xhr;
        }
    });
} else {
    // Proxy ajax
    ajax = $.ajax;
    $.ajax = function( settings ) {
        var mode = ( "mode" in settings ? settings : $.ajaxSettings ).mode,
            port = ( "port" in settings ? settings : $.ajaxSettings ).port;
        if ( mode === "abort" ) {
            if ( pendingRequests[port] ) {
                pendingRequests[port].abort();
            }
            pendingRequests[port] = ajax.apply(this, arguments);
            return pendingRequests[port];
        }
        return ajax.apply(this, arguments);
    };
}

Чтобы вам просто нужно было установить параметр прервать, когда вы делаете запрос ajax.

Ссылка: /jquery.validate.js

0

JQuery: Используйте это как отправную точку - как вдохновение. Я решил это так:  (это не идеальное решение, оно просто отменяет последний экземпляр и является кодом WIP)

var singleAjax = function singleAjax_constructor(url, params) {
    // remember last jQuery get request
    if (this.lastInstance) {
        this.lastInstance.abort();  // triggers .always() and .fail()
        this.lastInstance = false;
    }

    // how to use Deferred : http://api.jquery.com/category/deferred-object/
    var $def = new $.Deferred();

    // pass the deferrer request handlers into the get response handlers
    this.lastInstance = $.get(url, params)
        .fail($def.reject)         // triggers .always() and .fail()
        .success($def.resolve);    // triggers .always() and .done()

    // return the deferrer "control object", the promise object
    return $def.promise();
}


// initiate first call
singleAjax('/ajax.php', {a: 1, b: 2})
    .always(function(a,b,c) {console && console.log(a,b,c);});

// second call kills first one
singleAjax('/ajax.php', {a: 1, b: 2})
    .always(function(a,b,c) {console && console.log(a,b,c);});
    // here you might use .always() .fail() .success() etc.
0

Когда вы делаете запрос на сервер, попросите его проверить, не проделан ли прогресс не null (или выборка данных). Если он извлекает данные, отмените предыдущий запрос и инициируйте новый.

var progress = null

function fn () {    
    if (progress) {
        progress.abort();
    }
    progress = $.ajax('ajax/progress.ftl', {
        success: function(data) {
            //do something
            progress = null;
        }
    });
}
-1

Метод jQuery ajax возвращает объект XMLHttpRequest. Вы можете использовать этот объект для отмены запроса.

$(document).ready(
    var xhr;
    var fun = function(){
        if(xhr && xhr.readyState != 4){
            xhr.abort();
        }

        xhr = $.ajax({
            url: 'ajax/progress.ftl',
            success: function(data) {
                //do something code here
            }
        });
    };

    var interval = setInterval(fun, 1000);
);

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

-8

Вы также должны проверить наличие readyState 0. Так как при использовании xhr.abort() эта функция устанавливает readyState в 0 в этом объекте, а ваша проверка if всегда будет true - readyState!= 4

$(document).ready(
    var xhr;

    var fn = function(){
        if(xhr && xhr.readyState != 4 && xhr.readyState != 0){
            xhr.abort();
        }
        xhr = $.ajax({
            url: 'ajax/progress.ftl',
            success: function(data) {
                //do something
            }
        });
    };

    var interval = setInterval(fn, 500);
); 
  • 2
    Вы скопировали и вставили ответ Аруна? Потому что вероятность того, что два кодовых блока будут одинаковыми, с пробелами и т. Д.
  • 0
    @ user2700923 Его пост не совсем такой же. Суть его в том, что мы должны также проверить готовность к состоянию 0. Однако это было бы более уместно в качестве комментария к ответу Аруна.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню