使用jQuery中止Ajax请求
技术背景
在前端开发中,使用Ajax可以在不刷新整个页面的情况下与服务器进行异步通信。但在某些场景下,比如用户快速多次触发请求、页面卸载等,需要中止正在进行的Ajax请求,以避免不必要的服务器负载和客户端资源浪费。jQuery提供了便捷的方式来处理Ajax请求的中止。
实现步骤
1. 获取请求对象
大多数jQuery的Ajax方法都会返回一个XMLHttpRequest(或等效)对象,从jQuery 1.5开始返回的是一个名为jqXHR的原生XMLHttpRequest对象的包装器,从jQuery 3开始,ajax方法返回一个带有额外方法(如abort)的Promise对象。
2. 调用abort方法
通过调用返回对象的abort()
方法来中止请求。
核心代码
基本示例
1 2 3 4 5 6 7 8 9 10 11
| var xhr = $.ajax({ type: "POST", url: "some.php", data: "name=John&location=Boston", success: function(msg){ alert( "Data Saved: " + msg ); } });
xhr.abort();
|
结合计数器忽略旧响应
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| var xhrCount = 0; function sendXHR() { var seqNumber = ++xhrCount; $.post("/echo/json/", { delay: Math.floor(Math.random() * 5) }, function() { if (seqNumber === xhrCount) { console.log("Process the response"); } else { console.log("Ignore the response"); } }); } sendXHR(); sendXHR(); sendXHR();
|
防止重复请求示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| var Ajax3 = { active: false, call: function() { if (this.active === false) { this.active = true; var self = this; $.ajax({ url: 'your/long/running/request/path', type: 'GET', success: function(data) { }, complete: function() { self.active = false; } }); } } }; $(function() { $('#button').click(function(e) { Ajax3.call(); }); });
|
最佳实践
- 在发起新请求之前,先检查是否有未完成的请求,如果有则中止它,避免过多的请求堆积。
1 2 3 4 5 6 7 8 9 10 11 12 13
| var $request; if ($request != null){ $request.abort(); $request = null; }
$request = $.ajax({ type : "POST", url : "yourfile.php", data : "data" }).done(function(msg) { alert(msg); });
|
- 对于需要频繁触发的请求,如搜索框的实时搜索,可以设置一个延迟时间,减少不必要的请求。
1 2 3 4 5 6 7 8 9 10 11 12
| var xhrQueue = []; var xhrCount = 0;
$('#search_q').keyup(function(){ xhrQueue.push(xhrCount); setTimeout(function(){ xhrCount = ++xhrCount; if (xhrCount === xhrQueue.length) { } }, 150); });
|
常见问题
1. 中止请求后服务器仍在处理
由于Ajax请求是异步的,客户端中止请求并不意味着服务器会停止处理。如果使用PHP或ASP等带有会话数据的服务器端语言,会话数据会被锁定直到请求完成。可以在服务器端调用session_write_close()
来释放会话锁。
2. abort()
导致页面重新加载
可以在调用abort()
之前设置onreadystatechange
为null
来防止页面重新加载。
1 2 3 4
| xhr.onreadystatechange = null;
xhr.abort();
|