2009-09-16 50 views
23

Tôi có một hộp thoại jQuery mở ra và sau đó thực hiện cuộc gọi AJAX. Tôi muốn làm cho nó để nếu hộp thoại được đóng lại hoặc nút hủy được nhấn cuộc gọi AJAX bị hủy bỏ và chức năng gọi lại của nó không được gọi. Tôi có thể nghĩ đến một số cách để làm điều đó với một biến như sau:Hủy cuộc gọi jQuery AJAX trước khi nó trở về?

function doStuff(){ 
    var doCallback = true; 
    $('#dialog').dialog({ 
     title: 'Dialog Title', 
     modal: true, 
     buttons: { 
     Cancel: function() { 
      doCallback = false; 
      doSomethingElse(); 
     } 
     } 
    }); 
    $.get('url/url/url', function(data){ 
     if(doCallback){ 
     doTheSuccessThing(data); 
     } 
    }); 
    } 

Nhưng, bằng cách nào đó mà cảm thấy bẩn với tôi và nó không thực sự ngăn chặn các cuộc gọi AJAX từ hoàn thành. Có cách nào tích hợp để hủy cuộc gọi AJAX không?

+0

Không phải thứ tôi đã thử, nhưng phương thức get() trả về XMLHttpRequest cơ bản, có thể hủy bỏ() ed. Điều đó có giúp được không? – Andy

+0

có thể trùng lặp của [Hủy yêu cầu ajax trước đó jquery] (http: // stackoverflow.com/questions/4342438/canceling-previous-ajax-request-jquery) – Phrogz

Trả lời

14

Ok, vậy dựa tắt của các gợi ý để sử dụng đối tượng XMLHttpRequest trả về bởi hàm $ .get tôi đến với điều này:

function doStuff(){ 
    var ajaxRequest = $.ajax({ 
         url : 'url/url/url', 
         type : "GET", 
         success : function(data){ 
          ajaxRequest = null; 
          doSuccessStuff(data); 
         } 
         }); 

    $('#dialog').dialog({ 
     title: 'Stuff Dialog', 
     bgiframe: true, 
     modal: true, 
     buttons: { 
     Cancel: function() { 
      if (ajaxRequest) 
      ajaxRequest.abort(); 
      doCancelStuff(); 
     } 
     } 
    }); 
    } 

Dường làm việc và cảm thấy sạch hơn với tôi.

+3

đừng quên kiểm tra ajaxRequest là null. bạn nên đặt lại nó trong phương thức 'thành công' - sau đó bạn có thể đánh giá xem có yêu cầu ajax đang hoạt động hay không –

+0

'doSuccessStuff()' có thể vẫn được gọi ngay cả sau khi bạn hủy yêu cầu. Xem câu trả lời của tôi bên dưới để biết kỹ thuật bảo vệ chống lại điều này. – Phrogz

4

Dường như vậy, mặc dù tôi chưa bao giờ thực hiện.

$.get trả về đối tượng XmlHttpRequest, có phương thức abort() bạn có thể gọi. Có thể thử điều đó?

5

Không có phương pháp nào trong jQuery, nhưng bạn chỉ có thể sử dụng đối tượng XmlHttpRequest được trả về từ các hàm jQuery get/post/ajax.

Từ jQuery blog:

// Perform a simple Ajax request 
var req = $.ajax({ 
    type: "GET", 
    url: "/user/list/", 
    success: function(data) { 
    // Do something with the data... 
    // Then remove the request. 
    req = null; 
    } 
}); 

// Wait for 5 seconds 
setTimeout(function(){ 
    // If the request is still running, abort it. 
    if (req) req.abort(); 
}, 5000); 
17

Khi tôi có một callback có thể bị sa thải nhiều lần, nhưng tôi muốn chỉ sử dụng cuối cùng, tôi sử dụng mô hình này:

var resultsXHR, resultsTimer, resultsId=0; 
$('input').keyup(function(){ 
    clearTimeout(resultsTimer);      // Remove any queued request 
    if (resultsXHR) resultsXHR.abort();    // Cancel request in progress 
    resultsTimer = setTimeout(function(){   // Record the queued request 
    var id = ++resultsId;       // Record the calling order 
    resultsXHR = $.get('/results',function(data){ // Capture request in progress 
     resultsXHR = null;       // This request is done 
     if (id!=resultsId) return;     // A later request is pending 
     // ... actually do stuff here ... 
    }); 
    },500);           // Wait 500ms after keyup 
}); 

Các mình abort() là không đủ để ngăn chặn các cuộc gọi lại thành công từ được viện dẫn; bạn vẫn có thể tìm thấy cuộc gọi lại của mình mặc dù bạn đã cố gắng hủy yêu cầu. Đây là lý do tại sao cần sử dụng trình theo dõi resultsId và yêu cầu xử lý dừng gọi lại của bạn nếu một trình duyệt khác, sau đó, gọi lại chồng chéo đã sẵn sàng.

Vì mức độ phổ biến và cồng kềnh này, tôi nghĩ nên kết hợp nó theo kiểu có thể sử dụng lại mà không yêu cầu bạn phải tạo ra một bộ ba tên biến cục bộ cho mỗi tên bạn muốn xử lý:

(function($){ 
    $.fn.bindDelayedGet = function(event,delay,url,dataCallback,dataType,callback){ 
    var xhr, timer, ct=0; 
    return this.bind(event,function(){ 
     clearTimeout(timer); 
     if (xhr) xhr.abort(); 
     timer = setTimeout(function(){ 
     var id = ++ct; 
     xhr = $.get(url,dataCallback && dataCallback(),function(data){ 
      xhr = null; 
      if (id==ct) callback(data); 
     },dataType); 
     },delay); 
    }); 
    }; 
})(jQuery); 

// In action 
var inp = $('#myinput').bindDelayedGet('keyup',400,'/search', 
    function(){ return {term:inp.val()}; }, 
    'html', 
    function(html){ $('#searchResults').clear().append(html); } 
); 

Bạn có thể tìm thấy mã ở trên được thảo luận chi tiết hơn on my website.

+0

Tôi tự hỏi làm thế nào tôi có thể làm điều này trong bối cảnh của xương sống? –

+0

Mã ở trên cùng hoạt động hoàn hảo với tôi –

0

Nếu bạn đặt điều kiện trong tập lệnh bạn ajax vào điều kiện đúng, bạn xuất html của mình, nếu không, bạn không xuất được gì, sau đó bạn có thể làm đơn giản nếu (html) kiểm tra chức năng thành công như thế này:

$.ajax({ 
     type: "GET", 
     url: "url.php", 
     data: "data="+data, 
     success: function(html) 
      { 
       if(html){ 
       $("#container").empty().html(html); 
       } 
     } 
}); 

trong ví dụ này, url.php có thể trông giống như thế này:

$data = $_GET['data']; 

if($data=="whatever"){ 
    echo "<div>Hello</div>"; 
}else{} 

này đã làm việc cho tôi. Tôi biết bài đăng này là cũ, nhưng hy vọng nó giúp một ai đó.

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