如何取消/中止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);
);
257715 次浏览

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

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

xhr对象还包含一个请求处理,它包含请求的状态(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秒,会发生什么?

如果随请求传递的参数没有改变,则不应该中止请求。 例:-该请求是为了检索通知数据。 在这种情况下,最好的方法是在完成前一个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);


);

当您向服务器发出请求时,请先检查进度是否为空(或获取该数据)。如果它正在获取数据,则终止前一个请求并初始化新请求。

var progress = null


function fn () {
if (progress) {
progress.abort();
}
progress = $.ajax('ajax/progress.ftl', {
success: function(data) {
//do something
progress = null;
}
});
}
< p > 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.

您还应该检查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) {}

你可以使用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

创建一个函数来调用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()