2010-12-29 44 views
229

Tôi đã có yêu cầu AJAX sẽ được thực hiện sau mỗi 5 giây. Nhưng vấn đề là trước yêu cầu AJAX nếu yêu cầu trước đó không được hoàn thành, tôi đã hủy yêu cầu đó và đưa ra yêu cầu mới.Làm cách nào để hủy/hủy yêu cầu jQuery AJAX?

Mã của tôi giống như thế này, cách giải quyết vấn đề này?

$(document).ready(
    var fn = function(){ 
     $.ajax({ 
      url: 'ajax/progress.ftl', 
      success: function(data) { 
       //do something 
      } 
     }); 
    }; 

    var interval = setInterval(fn, 500); 
); 
+10

thể trùng lặp của [. Giết yêu cầu ajax sử dụng javascript sử dụng jquery] (http://stackoverflow.com/questions/446594/kill-ajax-requests-using-javascript-using-jquery) – karim79

+5

Câu hỏi của bạn cho biết yêu cầu sẽ xảy ra sau mỗi 5 giây, nhưng mã sử dụng 500 ms = 0.5 s. – geon

Trả lời

331

Phương thức jquery ajax trả về đối tượng XMLHttpRequest. Bạn có thể sử dụng đối tượng này để hủy yêu cầu.

Các XMLHttpRequest có một phương pháp abort, mà hủy bỏ yêu cầu, nhưng nếu yêu cầu đã được gửi đến máy chủ sau đó máy chủ sẽ xử lý yêu cầu thậm chí nếu chúng ta hủy bỏ yêu cầu nhưng khách hàng sẽ không phải chờ đợi/xử lý phản hồi.

Đối tượng xhr cũng chứa readyState chứa trạng thái yêu cầu (UNSENT-0, OPENED-1, HEADERS_RECEIVED-2, LOADING-3 và DONE-4). chúng ta có thể sử dụng điều này để kiểm tra xem yêu cầu trước đó đã được hoàn thành chưa.

$(document).ready(
    var xhr; 

    var fn = function(){ 
     if(xhr && xhr.readyState != 4){ 
      xhr.abort(); 
     } 
     xhr = $.ajax({ 
      url: 'ajax/progress.ftl', 
      success: function(data) { 
       //do something 
      } 
     }); 
    }; 

    var interval = setInterval(fn, 500); 
); 
+3

@rtpHarry Cảm ơn bạn đã cập nhật wrt jQuery 1.5 –

+59

@romkyns Sự khác biệt là thuộc tính 'readystate' ở trên và' readyState' bên dưới, ký tự 's' được viết hoa trong jQuery 1.5 –

+1

Thật vậy, cảm ơn! –

3

Tại sao bạn nên hủy yêu cầu?

Nếu mỗi yêu cầu mất hơn năm giây, điều gì sẽ xảy ra?

Bạn không nên hủy yêu cầu nếu tham số truyền với yêu cầu không thay đổi. ví dụ: - yêu cầu để truy xuất dữ liệu thông báo. Trong những trường hợp như vậy, Cách tiếp cận tốt đẹp là thiết lập một yêu cầu mới chỉ sau khi hoàn thành yêu cầu Ajax trước đó.

$(document).ready(

    var fn = function(){ 

     $.ajax({ 
      url: 'ajax/progress.ftl', 
      success: function(data) { 
       //do something 
      }, 

      complete: function(){setTimeout(fn, 500);} 
     }); 
    }; 

    var interval = setTimeout(fn, 500); 

); 
+3

Đây là một ý tưởng tồi. Khi bắt đầu cuộc gọi mới, bạn không muốn sự kiện hoàn thành được kích hoạt cuộc gọi trước đó. Bạn có thể nhận được kết quả rất lạ với cách tiếp cận này. – Webberig

+0

@Webberig Cảm ơn! đã cập nhật câu trả lời với tình huống. –

0

Khi bạn yêu cầu máy chủ, hãy kiểm tra xem liệu tiến trình không phải là rỗng (hoặc tìm nạp dữ liệu đó) trước tiên. Nếu nó đang tìm nạp dữ liệu, hãy hủy yêu cầu trước đó và khởi tạo yêu cầu mới.

var progress = null 

function fn() {  
    if (progress) { 
     progress.abort(); 
    } 
    progress = $.ajax('ajax/progress.ftl', { 
     success: function(data) { 
      //do something 
      progress = null; 
     } 
    }); 
} 
0

jQuery: Sử dụng điểm khởi đầu này làm nguồn cảm hứng. Tôi giải quyết nó như thế này: (đây không phải là một giải pháp hoàn hảo, nó chỉ hủy bỏ các trường hợp cuối cùng và là mã WIP)

var singleAjax = function singleAjax_constructor(url, params) { 
    // remember last jQuery's get request 
    if (this.lastInstance) { 
     this.lastInstance.abort(); // triggers .always() and .fail() 
     this.lastInstance = false; 
    } 

    // how to use Deferred : http://api.jquery.com/category/deferred-object/ 
    var $def = new $.Deferred(); 

    // pass the deferrer's request handlers into the get response handlers 
    this.lastInstance = $.get(url, params) 
     .fail($def.reject)   // triggers .always() and .fail() 
     .success($def.resolve); // triggers .always() and .done() 

    // return the deferrer's "control object", the promise object 
    return $def.promise(); 
} 


// initiate first call 
singleAjax('/ajax.php', {a: 1, b: 2}) 
    .always(function(a,b,c) {console && console.log(a,b,c);}); 

// second call kills first one 
singleAjax('/ajax.php', {a: 1, b: 2}) 
    .always(function(a,b,c) {console && console.log(a,b,c);}); 
    // here you might use .always() .fail() .success() etc. 
-7

Bạn cũng nên kiểm tra readyState 0. Bởi vì khi bạn sử dụng xhr.abort () chức năng này thiết lập readyState 0 trong đối tượng này, và nếu séc của bạn sẽ luôn luôn đúng - readyState = 4

$(document).ready(
    var xhr; 

    var fn = function(){ 
     if(xhr && xhr.readyState != 4 && xhr.readyState != 0){ 
      xhr.abort(); 
     } 
     xhr = $.ajax({ 
      url: 'ajax/progress.ftl', 
      success: function(data) { 
       //do something 
      } 
     }); 
    }; 

    var interval = setInterval(fn, 500); 
); 
+2

Bạn đã sao chép và dán câu trả lời của Arun chưa? Bởi vì khả năng của hai khối mã như vậy là chính xác như nhau, khoảng cách và tất cả ... –

+0

@ user2700923 Bài viết của ông là không chính xác như nhau. Quan điểm của anh ta là chúng ta cũng nên kiểm tra readyState 0. Tuy nhiên điều này sẽ thích hợp hơn với tư cách là bình luận cho câu trả lời của Arun. – Stefan

5

tôi biết điều này có thể là hơi muộn nhưng tôi gặp vấn đề tương tự mà gọi phương thức hủy bỏ didnt thực sự hủy bỏ yêu cầu. thay vào đó, trình duyệt vẫn đang chờ phản hồi mà nó không bao giờ sử dụng. mã này đã giải quyết vấn đề đó.

try { 
     xhr.onreadystatechange = null; 
     xhr.abort(); 
} catch (e) {} 
+0

Có cùng một vấn đề và điều này làm việc. –

0

Bạn có thể sử dụng jquery-validate.js. Sau đây là đoạn mã từ jquery-validate.js.

// ajax mode: abort 
// usage: $.ajax({ mode: "abort"[, port: "uniqueport"]}); 
// if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort() 

var pendingRequests = {}, 
    ajax; 
// Use a prefilter if available (1.5+) 
if ($.ajaxPrefilter) { 
    $.ajaxPrefilter(function(settings, _, xhr) { 
     var port = settings.port; 
     if (settings.mode === "abort") { 
      if (pendingRequests[port]) { 
       pendingRequests[port].abort(); 
      } 
      pendingRequests[port] = xhr; 
     } 
    }); 
} else { 
    // Proxy ajax 
    ajax = $.ajax; 
    $.ajax = function(settings) { 
     var mode = ("mode" in settings ? settings : $.ajaxSettings).mode, 
      port = ("port" in settings ? settings : $.ajaxSettings).port; 
     if (mode === "abort") { 
      if (pendingRequests[port]) { 
       pendingRequests[port].abort(); 
      } 
      pendingRequests[port] = ajax.apply(this, arguments); 
      return pendingRequests[port]; 
     } 
     return ajax.apply(this, arguments); 
    }; 
} 

Vì vậy mà bạn chỉ cần chỉ cần đặt tham số chế độ để hủy bỏ khi bạn đang làm theo yêu cầu ajax.

Ref: https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.14.0/jquery.validate.js

Các vấn đề liên quan