Tìm kiếm trang web

javascript - Hủy các yêu cầu Ajax sử dụng jQuery


Có khả thi không nếu sử dụng jQuery, tôi hủy/bỏ một yêu cầu Ajax mà tôi chưa nhận được phản hồi?

Câu trả lời #1

Hầu hết các phương thức jQuery Ajax trả về một đối tượng XMLHttpRequest (hoặc tương đương), vì vậy bạn chỉ cần sử dụng abort().

Xem tài liệu:

  • Phương thức abort (MSDN). Hủy yêu cầu HTTP hiện tại.
  • abort() (MDN). Nếu yêu cầu đã được gửi, phương thức này sẽ hủy 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: Từ jQuery 1.5 trở đi, đối tượng trả về là một lớp bao cho đối tượng XMLHttpRequest gốc được gọi là jqXHR. Đối tượng này dường như phơi bày tất cả các thuộc tính và phương thức gốc, vì vậy 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: Từ jQuery 3 trở đi, phương thức ajax hiện trả về một promise với các phương thức bổ sung (như abort), vì vậy mã trên vẫn hoạt động, mặc dù đối tượng được trả về không còn là xhr 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 cập nhật 2 là đúng. Thêm thông tin trên kho lưu trữ Github của jQuery.

Câu trả lời số 2

Bạn không thể gọi lại yêu cầu nhưng bạn có thể đặt một giá trị thời gian chờ sau đó phản hồi sẽ bị bỏ qua. Xem trang này để biết các tùy chọn AJAX của jQuery. Tôi tin rằng callback lỗi của bạn sẽ được gọi nếu thời gian chờ bị vượt quá. Đã có một thời gian chờ mặc định trên mỗi yêu cầu AJAX.

Bạn cũng có thể sử dụng phương thức abort() trên đối tượng request nhưng, trong khi nó sẽ khiến client dừng lắng nghe sự kiện, nó có thể có lẽ sẽ không ngăn server xử lý nó.

Câu trả lời #3

Lưu các cuộc gọi bạn thực hiện vào một mảng, sau đó gọi xhr.abort() trên từng cái.

CẢNH BÁO LỚN: Bạn có thể hủy một yêu cầu, nhưng đó chỉ là phía client. Phía server vẫn có thể đang xử lý yêu cầu. Nếu bạn đang sử dụng thứ gì đó như PHP hoặc ASP với dữ liệu session, dữ liệu session 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 web, bạn phải gọi session_write_close(). Điều này sẽ lưu session và mở khóa nó để các trang khác đang chờ tiếp tục có thể tiến hành. Nếu không có điều này, vài trang có thể đang chờ để khóa được gỡ bỏ.

Câu trả lời #4

Đây là một yêu cầu bất đồng bộ, có nghĩa là khi nó được gửi đi thì nó đã được phát ra ngoài.

Trong trường hợp máy chủ của bạn đang bắt đầu một thao tác rất tốn kém do yêu cầu AJAX, điều tốt nhất bạn có thể làm là mở máy chủ của bạn để lắng nghe các 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ủ ngừng bất cứ việc gì nó đang làm.

Nếu không, chỉ cần bỏ qua phản hồi AJAX.

Câu trả lời số 5

Các 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ạ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 bộ đếm
  • Tăng bộ đếm khi bạn khởi tạo 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 hàm gọi lại thành công, so sánh dấu thời gian với bộ đếm để kiểm tra xem đó có phải là yêu cầu mới nhất không

Phác thảo sơ bộ 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

Trình diễn trên jsFiddle

Câu trả lời số 6

Luôn luôn là thực hành tốt nhất khi làm một việc 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 một câu lệnh if để kiểm tra xem yêu cầu ajax có phải là null hay không.

Câu trả lời #7

Chúng tôi chỉ phải tìm cách giải quyết vấn đề này và đã thử ba phương pháp khác nhau.

  1. hủy yêu cầu như được @meouw gợi ý
  2. 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
  3. 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 #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% liệu jQuery có đảm bảo việc gọi phương thức .complete() hay không, điều này có thể tạo ra tình huống deadlock. Trong các bài kiểm tra của chúng tôi, chúng tôi không thể tái hiện được tình huống như vậy.

Câu trả lời số 8

Chỉ cần gọi xhr.abort() dù đó là đối tượng ajax của jquery hay đối tượng XMLHTTPRequest gốc.

ví 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);

Câu trả lời #9

Bạn có thể hủy bất kỳ cuộc gọi ajax liên tục nào bằng cách sử dụng điều này

<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>

Câu trả lời số 10

Như nhiều người trong chuỗi đã chỉ ra, chỉ vì yêu cầu bị hủy bỏ ở phía khách hàng, 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 thực hiện công việc mà chúng ta đã ngừng lắng nghe ở phía giao diện người dùng.

Vấn đề mà tôi đang cố gắng giải quyết (mà 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 một trường nhập liệu, tôi muốn gửi một yêu cầu để tạo cảm giác tương tự Google Instant.

Để tránh gửi những yêu cầu không cần thiết và duy trì sự nhạy bén của giao diện người dùng, tôi đã làm những điều 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 mỗi 150ms (một biến mà bạn có thể tùy chỉnh theo nhu cầu của riêng bạn). 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 ghi lại xhrCount và xhrQueue vào console ngay trước khối if.

Câu trả lời số 11

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ờ có thể đã mất nhiều thời gian hơn so với yêu cầu mới nhất/hiện tạ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 

Câu trả lời số 12

Chỉ cần sử dụng ajax.abort(), ví dụ bạn có thể hủy bất kỳ yêu cầu ajax đang chờ nào trước khi gửi một yêu cầu khác như sau

//check for existing ajax request
if(ajax){ 
 ajax.abort();
 }
//then you make another ajax request
$.ajax(
 //your code here
  );

Câu trả lời số 13

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ử; một khi yêu cầu đã được triển khai, cách duy nhất để phản ứng hợp lý là phớt lờ phản hồi.

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ư: một người dùng nhấp quá nhiều vào một nút, kích hoạt nhiều XHR liên tiếp. Ở đây, bạn có nhiều lựa chọn: hoặc block nút cho đến khi XHR được trả về, hoặc không kích hoạt XHR mới khi một XHR khác đang chạy, gợi ý người dùng nên thư giãn - hoặc bỏ qua bất kỳ phản hồi XHR đang chờ nào ngoài phản hồi gần nhất.

Bài viết liên quan