1.7k

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ừ đó?

|
  • 2

    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?

    – Hồ Thành Doanh 11:47:00 13/09/2013
  • 15

    @LukeMadhanga; Tôi nghĩ rằng ajaxStopchỉ 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.

    – Lý Hữu Trung 11:35:50 09/12/2013
1.6k

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:

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 xhrcò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, abortkhông đóng kết nối được thiết lập với máy chủ, vì vậy successsẽ 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.

    – Ngô Việt Nhân 12:31:19 12/03/2011
  • 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

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

    – Tạ Kim Ngọc 10:00:00 11/10/2017
110

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ó thể sẽ không ngăn máy chủ xử lý nó.

|
71

Đó 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.

|
64

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

|
52

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

Bản demo trên jsFiddle

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

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. không hủy yêu cầu theo đề xuất của @meouw
  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 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.

|
33

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.

|
20

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.

|
12

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);
|
12

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

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 xhrCountxhrQueuevào bảng điều khiển ngay trước khối if.

|
9

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.

|
9

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

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

Đ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âu trả lời của bạn (> 20 ký tự)

Bằng cách click "Đăng trả lời", bạn đồng ý với Điều khoản dịch vụ, Chính sách bảo mật and Chính sách cookie của chúng tôi.

Không tìm thấy câu trả lời bạn tìm kiếm? Duyệt qua các câu hỏi được gắn thẻ hoặc hỏi câu hỏi của bạn.