How do I make jQuery wait for an Ajax call to finish before it returns?
我有一个服务器端功能,需要登录。如果用户登录,函数将在成功时返回1。否则,函数将返回登录页面。
我想使用ajax和jquery调用函数。我要做的是用一个普通的链接提交请求,并在其上应用一个单击功能。如果用户未登录或函数失败,我希望Ajax调用返回true,以便href触发。
但是,当我使用以下代码时,函数在Ajax调用完成之前退出。
如何将用户优雅地重定向到登录页?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | $(".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 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | $(".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; } } }); }); |
但是,我会注意到这与Ajax的观点相反。另外,您应该在
我使用的不是
1 2 | $.ajaxSetup({async: false}); $.get("..."); |
基础的xmlhttpRequest对象(jquery用于发出请求)支持异步属性。设置为假。喜欢
1 | async: false |
您可以考虑在操作挂起时阻止UI,而不是将async设置为false(这通常是错误的设计)。
这可以通过jquery承诺很好地实现,如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | // 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(''); // 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(); } |
有了这个,你现在可以做:
1 2 3 4 5 6 7 8 | 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)); }); |
用户界面将一直阻塞,直到Ajax命令返回
参见JSFIDLE
我认为,如果编写
例如,您可以这样做,而不是返回
1 | window.location="appropriate page"; |
这样,当调用success函数时,页面就会被重定向。