如何让jQuery在返回之前等待Ajax调用完成?

我有一个服务器端功能,需要登录。如果用户登录成功,函数将返回1。如果不是,该函数将返回登录页面。

我想使用Ajax和jQuery调用该函数。我所做的是提交带有普通链接的请求,并在其上应用了单击功能。如果用户没有登录或函数失败,我希望ajax调用返回true,以便触发href。

但是,当我使用下面的代码时,函数在Ajax调用完成之前退出。

如何将用户优雅地重定向到登录页面?

$(".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;
}
}
});
});
461892 次浏览

如果你不希望$.ajax()函数立即返回,将async选项设置为false:

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

但是,我要指出,这与AJAX的观点是相反的。另外,你应该在faildone函数中处理响应。只有当从服务器接收到响应时,才会调用这些函数。

底层的XMLHttpRequest对象(由jQuery用于发出请求)支持 异步属性。设置为。像< / p >
async: false

我认为如果你编写你的success函数来加载适当的页面,而不是返回truefalse,事情会更容易。

例如,你可以这样做而不是返回true:

window.location="appropriate page";

这样,当成功函数被调用时,页面被重定向。

我没有使用$.ajax,而是使用$.post$.get函数,所以如果我需要等待响应,我使用这个:

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

与其将async设置为false(这通常是糟糕的设计),不如考虑在操作挂起时阻塞UI。

这可以很好地实现jQuery承诺如下:

// 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();
}

有了这个,你现在可以做:

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

UI将阻塞,直到ajax命令返回

看到jsfiddle

在现代JS中,你可以简单地使用async/await,比如:

  async function upload() {
return new Promise((resolve, reject) => {
$.ajax({
url: $(this).attr('href'),
type: 'GET',
timeout: 30000,
success: (response) => {
resolve(response);
},
error: (response) => {
reject(response);
}
})
})
}

然后在async函数中调用它,如下:

let response = await upload();

因为我在这里没有看到它,所以我想我也要指出jQuery 语句对于这个目的非常有用。

他们的例子如下:

$.when( $.ajax( "test.aspx" ) ).then(function( data, textStatus, jqXHR ) {
alert( jqXHR.status ); // Alerts 200
});

“then”部分直到“when”部分结束才执行。

它应该等待get请求完成。之后,我将从函数调用的地方返回get请求体。

function foo() {
var jqXHR = $.ajax({
url: url,
type: 'GET',
async: false,
});
return JSON.parse(jqXHR.responseText);
}

因为async ajax是不赞成的,尝试使用带有承诺的嵌套async函数。可能有语法错误。


async function fetch_my_data(_url, _dat) {


async function promised_fetch(_url, _dat) {


return new Promise((resolve, reject) => {
$.ajax({
url:  _url,
data: _dat,
type: 'POST',
success: (response) => {
resolve(JSON.parse(response));
},
error: (response) => {
reject(response);
}
});
});
}


var _data = await promised_fetch(_url, _dat);
   

return _data;
}


var _my_data = fetch_my_data('server.php', 'get_my_data=1');


最初的问题是在12年前的今天提出的,当时的问题是“如何让jQuery在返回之前等待Ajax调用完成?”从那时起,jQuery已经走过了很长的一段路。

上面提到了一些解决方案,但我无法让它们中的任何一个与最新版本的jQuery一起工作:$.when().then.()似乎不是同步的,除非它使用'async: false',这是不再支持的,所以不能在新版本的jQuery中工作。

但是承诺是内置在jQuery ajax调用中,因此使ajax调用同步应该不是那么困难。

我使用命名空间的js函数,所以下面的例子就是这种格式。示例是自定义表单验证,它调用服务器验证用户输入是否试图复制现有项。

除非使用Babel,否则这段代码可能无法在IE或Legacy Edge中工作,但我倾向于阻止这些浏览器,因为微软不再支持它们。

///Namespace validate
check: async function(settings){
let IsValid = false;
let Message = ''
let data = await validate.serverCheck('function', value);
IsValid = data.OK;
Message = data.Message;
}


serverCheck: async function (fn, value) {
var request = {
validateValue: $.sanitize(value)
};


let result;


try {
result = await $.ajax({
dataType: "json",
type: "post",
url: "/api/validate/" + fn + "/",
data: request
});


return result;
} catch (x) {}
}

结果出来了