2009-04-16 49 views
197

Tôi có một chức năng phía máy chủ yêu cầu đăng nhập. Nếu người dùng đăng nhập vào chức năng sẽ trả về 1 thành công. Nếu không, hàm sẽ trả về trang đăng nhập.Làm cách nào để jQuery chờ một cuộc gọi Ajax kết thúc trước khi nó trở về?

Tôi muốn gọi hàm bằng cách sử dụng Ajax và jQuery. Những gì tôi làm là gửi yêu cầu bằng liên kết thông thường, với chức năng nhấp được áp dụng trên đó. Nếu người dùng không đăng nhập hoặc chức năng bị lỗi, tôi muốn lệnh gọi Ajax trả về true, để href kích hoạt.

Tuy nhiên, khi tôi sử dụng mã sau, hàm sẽ thoát trước khi thực hiện cuộc gọi Ajax.

Làm cách nào để chuyển hướng người dùng một cách duyên dáng đến trang đăng nhập?

$(".my_link").click(
    function(){ 
    $.ajax({ 
     url: $(this).attr('href'), 
     type: 'GET', 
     cache: false, 
     timeout: 30000, 
     error: function(){ 
      return true; 
     }, 
     success: function(msg){ 
      if (parseFloat(msg)){ 
       return false; 
      } else { 
       return true; 
      } 
     } 
    }); 
}); 
+1

Có thể là một chuỗi cũ, nhưng khi @kofifus chỉ ra cài đặt sync to false là một thiết kế tồi và "không timeouts etc sẽ được xử lý". Có thể thử giải pháp đơn giản này - https: // stackoverflow.com/a/11576418/6937841 – Shan

Trả lời

295

Nếu bạn không muốn $.ajax() hàm trả về ngay lập tức, hãy đặt tùy chọn async-false:

$(".my_link").click(
    function(){ 
    $.ajax({ 
     url: $(this).attr('href'), 
     type: 'GET', 
     async: false, 
     cache: false, 
     timeout: 30000, 
     error: function(){ 
      return true; 
     }, 
     success: function(msg){ 
      if (parseFloat(msg)){ 
       return false; 
      } else { 
       return true; 
      } 
     } 
    }); 
}); 

Nhưng, tôi xin lưu ý rằng đây sẽ là ngược lại với quan điểm của AJAX. Ngoài ra, bạn nên xử lý phản hồi trong các hàm errorsuccess. Các chức năng này sẽ chỉ được gọi khi nhận được phản hồi từ máy chủ.

+1

Ý bạn là sai :) Tôi đoán? – veggerby

+0

Hah! Vâng cảm ơn. – cgp

+9

Vượt qua các thực hành tốt, theo ý kiến ​​của tôi, không phải là đánh giá, và là dấu hiệu của một số câu trả lời tốt nhất ở đây trên StackOverflow. – semperos

27

Đối tượng XMLHttpRequest cơ bản (được sử dụng bởi jQuery để thực hiện yêu cầu) hỗ trợ thuộc tính không đồng bộ . Đặt nó thành false. Giống như

async: false 
9

Tôi nghĩ mọi thứ sẽ dễ dàng hơn nếu bạn viết mã chức năng success của bạn để tải trang thích hợp thay vì trả lại true hoặc false.

Ví dụ thay vì trả lại true bạn có thể làm:

window.location="appropriate page"; 

Bằng cách đó khi chức năng thành công được gọi là trang được chuyển hướng.

30

Tôi không sử dụng $.ajax nhưng $.post$.get chức năng, vì vậy nếu tôi cần phải chờ câu trả lời, tôi sử dụng này:

$.ajaxSetup({async: false}); 
$.get("..."); 
+0

Điều này cũng phù hợp với $ .getJSON() ... có ý nghĩa –

17

Thay vì thiết lập async false đó là thiết kế thường xấu, bạn có thể muốn xem xét chặn giao diện người dùng trong khi thao tác đang chờ xử lý.

này có thể đạt độc đáo với jQuery hứa hẹn như sau:

// same as $.ajax but settings can have a maskUI property 
// if settings.maskUI==true, the UI will be blocked while ajax in progress 
// if settings.maskUI is other than true, it's value will be used as the color value while bloking (i.e settings.maskUI='rgba(176,176,176,0.7)' 
// in addition an hourglass is displayed while ajax in progress 
function ajaxMaskUI(settings) { 
    function maskPageOn(color) { // color can be ie. 'rgba(176,176,176,0.7)' or 'transparent' 
     var div = $('#maskPageDiv'); 
     if (div.length === 0) { 
      $(document.body).append('<div id="maskPageDiv" style="position:fixed;width:100%;height:100%;left:0;top:0;display:none"></div>'); // create it 
      div = $('#maskPageDiv'); 
     } 
     if (div.length !== 0) { 
      div[0].style.zIndex = 2147483647; 
      div[0].style.backgroundColor=color; 
      div[0].style.display = 'inline'; 
     } 
    } 
    function maskPageOff() { 
     var div = $('#maskPageDiv'); 
     if (div.length !== 0) { 
      div[0].style.display = 'none'; 
      div[0].style.zIndex = 'auto'; 
     } 
    } 
    function hourglassOn() { 
     if ($('style:contains("html.hourGlass")').length < 1) $('<style>').text('html.hourGlass, html.hourGlass * { cursor: wait !important; }').appendTo('head'); 
     $('html').addClass('hourGlass'); 
    } 
    function hourglassOff() { 
     $('html').removeClass('hourGlass'); 
    } 

    if (settings.maskUI===true) settings.maskUI='transparent'; 

    if (!!settings.maskUI) { 
     maskPageOn(settings.maskUI); 
     hourglassOn(); 
    } 

    var dfd = new $.Deferred(); 
    $.ajax(settings) 
     .fail(function(jqXHR, textStatus, errorThrown) { 
      if (!!settings.maskUI) { 
       maskPageOff(); 
       hourglassOff(); 
      } 
      dfd.reject(jqXHR, textStatus, errorThrown); 
     }).done(function(data, textStatus, jqXHR) { 
      if (!!settings.maskUI) { 
       maskPageOff(); 
       hourglassOff(); 
      } 
      dfd.resolve(data, textStatus, jqXHR); 
     }); 

    return dfd.promise(); 
} 

với điều này bây giờ bạn có thể làm:

ajaxMaskUI({ 
    url: url, 
    maskUI: true // or try for example 'rgba(176,176,176,0.7)' 
}).fail(function (jqXHR, textStatus, errorThrown) { 
    console.log('error ' + textStatus); 
}).done(function (data, textStatus, jqXHR) { 
    console.log('success ' + JSON.stringify(data)); 
}); 

Và giao diện người dùng sẽ chặn cho đến khi trở về lệnh ajax

xem jsfiddle

+0

Không đặt async thành false làm điều tương tự ngoại trừ trong một dòng mã? – Vincent

+3

Không có gì cả. Cài đặt async thành false làm cho yêu cầu không đồng bộ - đó là tạm dừng xử lý cho đến khi nó trả về thường là thực hành không tốt, ví dụ không có e lỗ thông hơi, các yêu cầu ajax khác, timeouts vv sẽ được xử lý. Bạn cũng có thể sửa đổi mã ở trên để chặn chỉ một phần của giao diện người dùng trong khi ajax của bạn đang xử lý (tức là phần nó sẽ ảnh hưởng) – kofifus

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