Sử dụng jQuery, làm cách nào tôi có thể hủy / hủy yêu cầu Ajax mà tôi chưa nhận được phản hồi từ đó?
Hầu hết các phương thức Ajax của jQuery trả về một đối tượng XMLHttpRequest (hoặc tương đương), vì vậy bạn chỉ có thể sử dụng abort()
.
Xem tài liệu:
- Phương pháp hủy bỏ ( MSDN ). Hủy yêu cầu HTTP hiện tại.
- hủy bỏ () ( MDN ). Nếu yêu cầu đã được gửi đi, phương thức này sẽ hủy bỏ yêu cầu.
var xhr = $.ajax({
type: "POST",
url: "some.php",
data: "name=John&location=Boston",
success: function(msg){
alert( "Data Saved: " + msg );
}
});
//kill the request
xhr.abort()
CẬP NHẬT: Kể từ jQuery 1.5, đối tượng được trả về là một trình bao bọc cho đối tượng XMLHttpRequest gốc được gọi là jqXHR. Đối tượng này dường như để lộ tất cả các thuộc tính và phương thức riêng nên ví dụ trên vẫn hoạt động. Xem Đối tượng jqXHR (tài liệu API jQuery).
CẬP NHẬT 2:
Kể từ jQuery 3, phương thức ajax hiện trả lại một lời hứa với các phương thức bổ sung (như hủy bỏ), vì vậy đoạn mã trên vẫn hoạt động, mặc dù đối tượng được trả về không xhr
còn nữa. Xem blog 3.0 tại đây .
CẬP NHẬT 3 : xhr.abort()
vẫn hoạt động trên jQuery 3.x. Đừng cho rằng bản cập nhật 2 là chính xác. Thông tin thêm về kho lưu trữ jQuery Github .
-
1
Giống như nhấp vào nút 'dừng' trên trình duyệt của bạn. Nó hủy bỏ yêu cầu. Sau đó, bạn có thể sử dụng lại cùng một đối tượng XHR cho một yêu cầu khác.
– Lý Kiên Trung 13:19:49 15/01/2009 -
1
@brad Thật không may,
– Ngô Việt Nhân 12:31:19 12/03/2011abort
không đóng kết nối được thiết lập với máy chủ, vì vậysuccess
sẽ vẫn được gọi. Điều này rất có vấn đề đối với việc triển khai Sao chổi với việc bỏ phiếu dài. -
1
@ErvWalter Bạn có thể gửi một yêu cầu khác hủy bỏ yêu cầu trước đó.
– Bùi Như Hảo 06:37:44 09/12/2012 -
1
Trong các thử nghiệm của tôi, yêu cầu bị hủy bỏ trên trình duyệt, nhưng phương thức .fail () được gọi với jqXHR, status = 0 và jqXHR, statusMessage = "hủy bỏ"
– Hoàng Khắc Thành 02:23:41 08/11/2013 -
1
– Tạ Kim Ngọc 10:00:00 11/10/2017.abort()
vẫn hoạt động với tôi trong jQuery 3.2.1. Nhận xét này trong một vấn đề github có liên quan của một thành viên nhóm cốt lõi jQuery dường như ngụ ý rằng câu trả lời này không chính xác và.abort()
không bị xóa.
Bạn không thể nhớ lại yêu cầu nhưng bạn có thể đặt giá trị hết thời gian chờ mà sau đó phản hồi sẽ bị bỏ qua. Xem trang này để biết các tùy chọn AJAX jquery. Tôi tin rằng cuộc gọi lại lỗi của bạn sẽ được gọi nếu vượt quá thời gian chờ. Đã có thời gian chờ mặc định cho mọi yêu cầu AJAX.
Bạn cũng có thể sử dụng phương thức hủy bỏ () trên đối tượng yêu cầu, nhưng, trong khi nó sẽ khiến máy khách ngừng lắng nghe sự kiện, nó có thể sẽ không ngăn máy chủ xử lý nó.
Đó là một yêu cầu không đồng bộ , nghĩa là một khi nó được gửi ra ngoài đó.
Trong trường hợp máy chủ của bạn đang bắt đầu một hoạt động rất tốn kém do yêu cầu AJAX, cách tốt nhất bạn có thể làm là mở máy chủ của mình để lắng nghe yêu cầu hủy và gửi một yêu cầu AJAX riêng để thông báo cho máy chủ dừng mọi hoạt động.
Nếu không, chỉ cần bỏ qua phản hồi AJAX.
-
1
Trong ngữ cảnh này, không đồng bộ đơn giản có nghĩa là yêu cầu không làm gián đoạn dòng chảy của tập lệnh. Trình duyệt hiện có khả năng hủy bỏ yêu cầu sớm trước khi yêu cầu được hoàn thành.
– Lý Kiên Trung 19:12:41 10/04/2012 -
1
Làm thế nào chúng ta có thể gửi yêu cầu hủy đến máy chủ? Tôi không hiểu làm thế nào máy chủ sẽ biết yêu cầu ngừng xử lý? Bạn có thể cho một ví dụ? Cảm ơn bạn.
– Ngô Việt Nhân 22:18:58 28/06/2014 -
1
@LuckySoni, Elephanthunter chỉ thảo luận về phía khách hàng. Máy chủ sẽ không bị ảnh hưởng bởi yêu cầu .abort
– Bùi Như Hảo 13:28:23 11/08/2014 -
1
@Kloar, nếu máy chủ chưa nhận được yêu cầu (ví dụ: yêu cầu nhiều phần lớn), máy khách có thể đóng ổ cắm và máy chủ sẽ bị ảnh hưởng.
– Hoàng Khắc Thành 09:17:47 20/09/2014 -
1
PHP tự động kiểm tra các yêu cầu bị hủy bỏ và cũng tự động chấm dứt. thấy php.net/manual/en/function.ignore-user-abort.php
– Tạ Kim Ngọc 19:58:39 01/03/2015
Lưu các cuộc gọi bạn thực hiện trong một mảng, sau đó gọi xhr.abort () trên mỗi mảng.
CAGEAT HUGE: Bạn có thể hủy bỏ yêu cầu, nhưng đó chỉ là phía khách hàng. Phía máy chủ vẫn có thể xử lý yêu cầu. Nếu bạn đang sử dụng một cái gì đó như PHP hoặc ASP với dữ liệu phiên, dữ liệu phiên sẽ bị khóa cho đến khi ajax kết thúc. Vì vậy, để cho phép người dùng tiếp tục duyệt trang web, bạn phải gọi session_write_close (). Điều này sẽ lưu phiên và mở khóa để các trang khác đang chờ tiếp tục sẽ tiếp tục. Nếu không có điều này, một vài trang có thể chờ khóa được gỡ bỏ.
Yêu cầu AJAX có thể không hoàn thành theo thứ tự chúng đã được bắt đầu. Thay vì hủy bỏ, bạn có thể chọn bỏ qua tất cả các phản hồi AJAX ngoại trừ phản hồi gần đây nhất:
- Tạo một quầy
- Tăng bộ đếm khi bạn bắt đầu yêu cầu AJAX
- Sử dụng giá trị hiện tại của bộ đếm để "đóng dấu" yêu cầu
- Trong cuộc gọi lại thành công, so sánh tem với bộ đếm để kiểm tra xem đó có phải là yêu cầu gần đây nhất không
Phác thảo thô của mã:
var xhrCount = 0;
function sendXHR() {
// sequence number for the current invocation of function
var seqNumber = ++xhrCount;
$.post("/echo/json/", { delay: Math.floor(Math.random() * 5) }, function() {
// this works because of the way closures work
if (seqNumber === xhrCount) {
console.log("Process the response");
} else {
console.log("Ignore the response");
}
});
}
sendXHR();
sendXHR();
sendXHR();
// AJAX requests complete in any order but only the last
// one will trigger "Process the response" message
-
1
Do cần phải hủy yêu cầu XHR (xem các bình luận khác trên trang này), đây có lẽ là tùy chọn tốt nhất và đơn giản nhất.
– Lý Kiên Trung 00:50:00 24/01/2019
Chúng tôi chỉ phải giải quyết vấn đề này và thử nghiệm ba cách tiếp cận khác nhau.
- không hủy yêu cầu theo đề xuất của @meouw
- thực hiện tất cả các yêu cầu nhưng chỉ xử lý kết quả của lần gửi cuối cùng
- ngăn chặn các yêu cầu mới miễn là một yêu cầu khác vẫn đang chờ xử lý
var Ajax1 = {
call: function() {
if (typeof this.xhr !== 'undefined')
this.xhr.abort();
this.xhr = $.ajax({
url: 'your/long/running/request/path',
type: 'GET',
success: function(data) {
//process response
}
});
}
};
var Ajax2 = {
counter: 0,
call: function() {
var self = this,
seq = ++this.counter;
$.ajax({
url: 'your/long/running/request/path',
type: 'GET',
success: function(data) {
if (seq === self.counter) {
//process response
}
}
});
}
};
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) {
//process response
},
complete: function() {
self.active = false;
}
});
}
}
};
$(function() {
$('#button').click(function(e) {
Ajax3.call();
});
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="button" type="button" value="click" />
Trong trường hợp của chúng tôi, chúng tôi đã quyết định sử dụng phương pháp số 3 vì nó tạo ra ít tải hơn cho máy chủ. Nhưng tôi không chắc chắn 100% nếu jQuery đảm bảo lệnh gọi của phương thức .complete () -, điều này có thể tạo ra tình huống bế tắc. Trong các thử nghiệm của chúng tôi, chúng tôi không thể tái tạo một tình huống như vậy.
Nó luôn luôn là thực hành tốt nhất để làm một cái gì đó như thế này.
var $request;
if ($request != null){
$request.abort();
$request = null;
}
$request = $.ajax({
type : "POST", //TODO: Must be changed to POST
url : "yourfile.php",
data : "data"
}).done(function(msg) {
alert(msg);
});
Nhưng sẽ tốt hơn nhiều nếu bạn kiểm tra câu lệnh if để kiểm tra xem yêu cầu ajax có null hay không.
-
1
Tôi cũng kiểm tra xem một yêu cầu đã chạy chưa, nhưng tôi sử dụng boolean, vì nó nhẹ hơn.
– Trịnh Mỹ Vân 05:02:27 29/07/2015
Giải pháp của meouw là chính xác, nhưng nếu bạn quan tâm đến việc kiểm soát nhiều hơn thì bạn có thể thử plugin Trình quản lý Ajax cho jQuery.
-
1
Link là chết và Web Archive bức ảnh chụp được 301 trang ... Tôi tìm thấy một ngã ba có vẻ như nó là plugin được đề cập: github.com/aFarkas/Ajaxmanager/blob/master/...
– Trịnh Mỹ Vân 11:55:37 11/06/2018
Chỉ cần gọi xhr. hủy bỏ () cho dù đó là đối tượng ajax jquery hoặc đối tượng XMLHTTPRequest riêng.
thí dụ:
//jQuery ajax
$(document).ready(function(){
var xhr = $.get('/server');
setTimeout(function(){xhr.abort();}, 2000);
});
//native XMLHTTPRequest
var xhr = new XMLHttpRequest();
xhr.open('GET','/server',true);
xhr.send();
setTimeout(function(){xhr.abort();}, 2000);
Tôi đang thực hiện một giải pháp tìm kiếm trực tiếp và cần hủy các yêu cầu đang chờ xử lý có thể mất nhiều thời gian hơn yêu cầu mới nhất / mới nhất.
Trong trường hợp của tôi, tôi đã sử dụng một cái gì đó như thế này:
//On document ready
var ajax_inprocess = false;
$(document).ajaxStart(function() {
ajax_inprocess = true;
});
$(document).ajaxStop(function() {
ajax_inprocess = false;
});
//Snippet from live search function
if (ajax_inprocess == true)
{
request.abort();
}
//Call for new request
Như nhiều người trong luồng đã lưu ý, chỉ vì yêu cầu bị hủy bỏ ở phía máy khách, máy chủ vẫn sẽ xử lý yêu cầu. Điều này tạo ra tải không cần thiết trên máy chủ vì nó đang hoạt động mà chúng tôi đã bỏ nghe ở mặt trước.
Vấn đề tôi đang cố gắng giải quyết (mà những người khác cũng có thể gặp phải) là khi người dùng nhập thông tin vào trường nhập liệu, tôi muốn loại bỏ yêu cầu về loại cảm giác Google Instant.
Để tránh thực hiện các yêu cầu không cần thiết và để duy trì sự nhanh nhẹn của giao diện người dùng, tôi đã làm như sau:
var xhrQueue = [];
var xhrCount = 0;
$('#search_q').keyup(function(){
xhrQueue.push(xhrCount);
setTimeout(function(){
xhrCount = ++xhrCount;
if (xhrCount === xhrQueue.length) {
// Fire Your XHR //
}
}, 150);
});
Điều này về cơ bản sẽ gửi một yêu cầu cứ sau 150ms (một biến mà bạn có thể tùy chỉnh theo nhu cầu của riêng mình). Nếu bạn gặp khó khăn trong việc hiểu chính xác những gì đang xảy ra ở đây, hãy đăng nhập xhrCount
và xhrQueue
vào bảng điều khiển ngay trước khối if.
không có cách nào đáng tin cậy để làm điều đó, và tôi thậm chí sẽ không thử nó, một khi yêu cầu được thực hiện; các chỉ cách để phản ứng một cách hợp lý là để bỏ qua các phản ứng.
trong hầu hết các trường hợp, điều này có thể xảy ra trong các tình huống như: người dùng nhấp quá thường xuyên vào nút kích hoạt nhiều XHR liên tiếp, ở đây bạn có nhiều tùy chọn, chặn nút cho đến khi XHR được trả lại hoặc thậm chí không kích hoạt XHR mới trong khi một người khác đang chạy gợi ý người dùng dựa lưng - hoặc loại bỏ bất kỳ phản hồi XHR đang chờ xử lý nào nhưng gần đây.
Chỉ cần sử dụng ajax.abort () ví dụ bạn có thể hủy bỏ mọi yêu cầu ajax đang chờ xử lý trước khi gửi một yêu cầu khác như thế này
//check for existing ajax request
if(ajax){
ajax.abort();
}
//then you make another ajax request
$.ajax(
//your code here
);
Bạn có thể hủy bỏ mọi cuộc gọi ajax liên tục bằng cách sử dụng
<input id="searchbox" name="searchbox" type="text" />
<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
<script type="text/javascript">
var request = null;
$('#searchbox').keyup(function () {
var id = $(this).val();
request = $.ajax({
type: "POST", //TODO: Must be changed to POST
url: "index.php",
data: {'id':id},
success: function () {
},
beforeSend: function () {
if (request !== null) {
request.abort();
}
}
});
});
</script>
Đoạn mã sau đây cho thấy bắt đầu cũng như hủy bỏ yêu cầu Ajax:
function libAjax(){
var req;
function start(){
req = $.ajax({
url: '1.php',
success: function(data){
console.log(data)
}
});
}
function stop(){
req.abort();
}
return {start:start,stop:stop}
}
var obj = libAjax();
$(".go").click(function(){
obj.start();
})
$(".stop").click(function(){
obj.stop();
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="button" class="go" value="GO!" >
<input type="button" class="stop" value="STOP!" >
-
1
Vui lòng cung cấp một lời giải thích về cách này giải quyết câu hỏi. Điều này sẽ giúp OP và những người tìm kiếm khác trong tương lai.
– Trịnh Mỹ Vân 00:48:14 29/01/2016
Có lẽ tôi đã hiểu nhầm câu hỏi, nhưng bạn không thể đơn giản sử dụng
– Hồ Thành Doanh 11:47:00 13/09/2013$.ajaxStop
?@LukeMadhanga; Tôi nghĩ rằng
– Lý Hữu Trung 11:35:50 09/12/2013ajaxStop
chỉ phát hiện khi tất cả các yêu cầu AJAX hoàn thành, nó không dừng yêu cầu. Theo kinh nghiệm của tôi, bạn sẽ sử dụng nó như thế này :$(document).ajaxStop(function(){alert("All done")})
. Sử dụng.abort()
là lựa chọn tốt nhất.