首页 文章

如何取消/中止jQuery AJAX请求?

提问于
浏览
233

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

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

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

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

8 回答

  • 0

    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);
    );
    
  • -7

    Why should you abort the request?

    如果每个请求超过五秒钟,会发生什么?

    如果随请求传递的参数未更改,则不应中止请求 . 例如: - 请求用于检索通知数据 . 在这种情况下,好方法是仅在完成先前的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);
    
    );
    
  • 5

    您还应该检查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);
    );
    
  • 1

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

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

    当您向服务器发出请求时,请先检查进度是否为空(或获取该数据) . 如果它正在获取数据,则中止先前的请求并启动新请求 .

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

    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.
    
  • 3

    您可以使用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请求时将参数 mode 设置为 abort .

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

  • 343

    创建一个调用API的函数 . 在这个函数中,我们定义了请求 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() .

相关问题