Câu hỏi Hủy bỏ các yêu cầu Ajax bằng cách sử dụng jQuery


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ừ đâu?


1637
2018-01-15 12:45


gốc


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 $.ajaxStop? - Luke Madhanga
@LukeMadhanga; Tôi nghĩ ajaxStop chỉ phát hiện khi tất cả các yêu cầu AJAX hoàn tất, 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. - TheCarver


Các câu trả lời:


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ó thể sử dụng abort().

Xem tài liệ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 trả về là một trình bao bọc cho đối tượng XMLHttpRequest nguyên gốc có tên là jqXHR. Đối tượng này xuất hiện để trưng ra tất cả các thuộc tính và phương thức gốc để 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 bây giờ trả về một lời hứa với các phương thức bổ sung (như hủy bỏ), vì vậy mã trên vẫn hoạt động, mặc dù đối tượng được trả về không phải là một xhr nữa không. Xem 3.0 blog 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 đúng. Thông tin thêm về kho lưu trữ jQuery Github.


1597
2018-01-15 12:56



Nó 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. - meouw
@brad Thật không may, abort không đóng kết nối được thiết lập với máy chủ, vì vậy success sẽ vẫn được gọi. Điều này là rất có vấn đề đối với việc triển khai Comet với việc bỏ phiếu dài. - pepkin88
@ErvWalter Bạn có thể gửi một yêu cầu khác hủy yêu cầu trước đó. - Asad Saeeduddin
Trong các thử nghiệm của tôi, yêu cầu bị hủy bỏ tại trình duyệt, nhưng phương thức .fail () được gọi với một jqXHR, status = 0, và jqXHR, statusMessage = "abort" - BJ Safdie
Nó sẽ không còn hoạt động cho jQuery 3.0 blog.jquery.com/2016/01/14/jquery-3-0-beta- phát hành - jcubic


Bạn không thể gọi lại yêu cầu nhưng bạn có thể đặt giá trị thời gian chờ mà sau đó phản hồi sẽ bị bỏ qua. Xem này trang cho các tùy chọn AJAX jquery. Tôi tin rằng lỗi gọi lại của bạn sẽ được gọi nếu thời gian chờ vượt quá. Đã có 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 hủy bỏ () phương pháp trên đối tượng yêu cầu nhưng, trong khi nó sẽ khiến khách hàng ngừng nghe cho sự kiện, nó có thể có thể sẽ không ngừng máy chủ xử lý nó.


106
2018-01-15 12:55





Đó là một không đồng bộ yêu cầu, có nghĩa là một khi nó được gửi nó ra khỏi đó.

Trong trường hợp máy chủ của bạn bắt đầu một hoạt động rất tốn kém do yêu cầu AJAX, tốt nhất bạn có thể làm là mở máy chủ của bạn để lắng nghe yêu cầu hủy và gửi yêu cầu AJAX riêng để thông báo cho máy chủ ngừng mọi thứ đang thực hiện.

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


70
2018-01-15 12:56



Trong bối cảnh này, không đồng bộ đơn giản nghĩa là yêu cầu không làm gián đoạn luồng của tập lệnh. Trình duyệt hiện có khả năng hủy yêu cầu sớm trước khi yêu cầu hoàn tất. - ElephantHunter
Làm cách nào chúng tôi có thể gửi yêu cầu hủy tới máy chủ? Tôi không hiểu máy chủ sẽ biết yêu cầu ngừng xử lý như thế nào? Bạn có thể đưa ra một ví dụ? Cảm ơn bạn. - Lucky Soni
@ 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 - Kloar
@ Kloar, nếu yêu cầu chưa được nhận bởi máy chủ (yêu cầu nhiều phần lớn của f.ex.), ứng dụng khách có thể đóng socket và máy chủ sẽ bị ảnh hưởng. - white
PHP tự động kiểm tra các yêu cầu bị hủy bỏ và tự động chấm dứt. xem php.net/manual/en/function.ignore-user-abort.php - hanshenrik


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.

HUGE CAVEAT: Bạn có thể hủy 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 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(). Thao tác này sẽ lưu phiên và mở nó để 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 số trang có thể chờ khóa bị xóa.


62
2018-03-28 11:34





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 câu trả lời AJAX ngoại trừ câu trả lời gần đây nhất:

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

Đường viền 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

Bản trình diễn trên jsFiddle


45
2018-01-18 12:55





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.

  1. hủy yêu cầu theo đề xuất của @meouw
  2. thực hiện tất 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 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 cho máy chủ. Nhưng tôi không chắc chắn 100% nếu jQuery đảm bảo cuộc 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 tình huống như vậy.


36
2018-03-06 14:29





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 nếu bạn kiểm tra câu lệnh if để kiểm tra xem yêu cầu ajax có rỗng hay không.


30
2017-10-15 09:14



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 một boolean, vì nó nhẹ hơn. - Zesty