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

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

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

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

    var interval = setInterval(fn, 500);
);

Ответ 1

Метод 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);
);

Ответ 2

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

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

Ответ 3

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

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

Ответ 4

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

var progress = null

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

Ответ 5

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

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

Вы не должны прерывать запрос, если параметр, передаваемый с запросом, не изменяется. например: - запрос на получение данных уведомления. В таких ситуациях приятным подходом является то, что задать новый запрос только после завершения предыдущего запроса 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);

);

Ответ 6

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.

Ответ 7

Вы можете использовать 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.

Ссылка: https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.14.0/jquery.validate.js

Ответ 8

Создайте функцию для вызова вашего API. В этой функции мы определяем request callApiRequest = $.get(... - хотя это определение переменной, запрос вызывается немедленно, но теперь мы определили запрос как переменную. Перед вызовом мы проверить, определена ли наша переменная typeof(callApiRequest) != 'undefined' а также, если она находится в состоянии ожидания. suggestCategoryRequest.state() == 'pending' - если оба значения верны, мы .abort() запрос, который предотвратит успешный обратный вызов от бега.

// We need to wrap the call in a function
callApi = function () {

    //check if request is defined, and status pending
    if (typeof(callApiRequest) != 'undefined'
        && suggestCategoryRequest.state() == 'pending') {

        //abort request
        callApiRequest.abort()

    }

    //define and make request
    callApiRequest = $.get("https://example.com", function (data) {

        data = JSON.parse(data); //optional (for JSON data format)
        //success callback

    });
}

Ваш сервер /API может не поддерживать прерывание запроса (что, если API уже выполнил некоторый код?), Но обратный вызов javascript не сработает. Это полезно, когда, например, вы предоставляете пользователю предложения ввода, такие как ввод хэштегов.

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

Распространенным вариантом использования этого фрагмента будет ввод текста, который запускается при keypress. Вы можете использовать тайм-аут, чтобы предотвратить отправку (некоторых) запросов, которые вам придется отменить .abort().

Ответ 9

Существует фиктивное решение, которое я использую для отмены всех запросов AJAX. Это решение перезагрузить всю страницу. Это решение хорошо, если вам не нравится присваивать ID каждому запросу ajax, и если вы делаете запросы ajax внутри цикла for. Это обеспечит уничтожение всех запросов AJAX.

location.reload();

Ответ 10

Метод 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);
);

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

Ответ 11

Вы также должны проверить наличие 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);
);