How to cancel/abort jQuery AJAX request?
我有一个每5秒钟发出一次AJAX请求。 但问题是在AJAX请求之前,如果先前的请求没有完成,我将中止该请求并发出新请求。
我的代码是这样的,如何解决这个问题?
1 2 3 4 5 6 7 8 9 10 11 12 | $(document).ready( var fn = function(){ $.ajax({ url: 'ajax/progress.ftl', success: function(data) { //do something } }); }; var interval = setInterval(fn, 500); ); |
jquery ajax方法返回XMLHttpRequest对象。您可以使用此对象取消请求。
XMLHttpRequest有一个中止方法,它取消了请求,但是如果请求已经发送到服务器,那么即使我们中止请求但服务器不会等待/处理响应,服务器也会处理请求。
xhr对象还包含readyState,其中包含请求的状态(UNSENT-0,OPENED-1,HEADERS_RECEIVED-2,LOADING-3和DONE-4)。我们可以用它来检查先前的请求是否已完成。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | $(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); ); |
我知道这可能有点晚了,但我遇到类似的问题,调用abort方法并没有真正中止请求。相反,浏览器仍在等待它从未使用过的响应。
此代码解决了该问题。
1 2 3 4 | try { xhr.onreadystatechange = null; xhr.abort(); } catch (e) {} |
当您向服务器发出请求时,请先检查进度是否为空(或获取该数据)。如果它正在获取数据,则中止先前的请求并启动新请求。
1 2 3 4 5 6 7 8 9 10 11 12 13 | var progress = null function fn () { if (progress) { progress.abort(); } progress = $.ajax('ajax/progress.ftl', { success: function(data) { //do something progress = null; } }); } |
你为什么要中止请求?
如果每个请求超过五秒钟,会发生什么?
如果随请求传递的参数未更改,则不应中止请求。
例如: - 请求用于检索通知数据。
在这种情况下,好的方法是在完成前一个Ajax请求后才设置新请求。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | $(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); ); |
创建一个调用API的函数。在这个函数中,我们定义了request
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | // 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回调不会触发。例如,当您向用户提供输入建议(例如主题标签输入)时,这很有用。
您可以通过添加错误回调的定义来进一步扩展此功能 - 如果请求被中止,应该会发生什么。
此代码段的常见用例是在
您可以使用jquery-validate.js。以下是jquery-validate.js的代码片段。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | // 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
jQuery的:
以此为出发点 - 作为灵感。
我这样解决了:
(这不是一个完美的解决方案,它只是中止最后一个实例并且是WIP代码)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | 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检查将始终为true - readyState!= 4
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | $(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); ); |