Как отменить / отменить JQuery AJAX-запрос? - PullRequest
236 голосов
/ 29 декабря 2010

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

Мой код примерно такой, как решить эту проблему?

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

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

Ответы [ 8 ]

346 голосов
/ 29 декабря 2010

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

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

Объект xhr также содержит readyState , в котором содержится состояние запроса (UNSENT-0, OPENED-1, HEADERS_RECEIVED-2, LOADING-3 и DONE-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);
);
5 голосов
/ 01 февраля 2015

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

 try {
        xhr.onreadystatechange = null;
        xhr.abort();
} catch (e) {}
2 голосов
/ 26 марта 2013

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

var progress = null

function fn () {    
    if (progress) {
        progress.abort();
    }
    progress = $.ajax('ajax/progress.ftl', {
        success: function(data) {
            //do something
            progress = null;
        }
    });
}
1 голос
/ 31 января 2013

Почему вы должны прервать запрос?

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

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

);
0 голосов
/ 07 сентября 2018

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

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

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

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

0 голосов
/ 15 октября 2015

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

Так что вам нужно только установить параметр mode на abort , когда высделав запрос ajax.

Ref: https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.14.0/jquery.validate.js

0 голосов
/ 24 октября 2013

Вы также должны проверить для 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);
); 
0 голосов
/ 12 июня 2013

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

var singleAjax = function singleAjax_constructor(url, params) {
    // remember last jQuery's 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's 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's "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.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...