我有一个AJAX请求,每5秒发出一次。但问题是在AJAX请求之前,如果之前的请求没有完成,我必须中止该请求,并做出一个新的请求。

我的代码是这样的,如何解决这个问题?

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

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

当前回答

您还应该检查readyState 0。因为当你使用xhr.abort()时,这个函数在这个对象中将readyState设置为0,并且你的if检查将始终为真- 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);
); 

其他回答

jquery ajax方法返回一个XMLHttpRequest对象。您可以使用此对象取消请求。

XMLHttpRequest有一个abort方法,它会取消请求,但是如果请求已经发送到服务器,那么即使我们中止请求,服务器也会处理请求,而客户端不会等待/处理响应。

xhr对象还包含一个readyState,它包含请求的状态(UNSENT-0, open -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);
);

你可以使用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请求时将参数模式设置为abort。

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

您还应该检查readyState 0。因为当你使用xhr.abort()时,这个函数在这个对象中将readyState设置为0,并且你的if检查将始终为真- 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);
); 

我知道这可能有点晚了,但我经历过类似的问题,调用abort方法并没有真正中止请求。相反,浏览器仍然在等待一个它从未使用过的响应。 这段代码解决了这个问题。

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

为什么要中止请求?

如果每个请求都超过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);

);