我有一个非常复杂的搜索,它使用多个ajax调用,流程如下:
user performs search on button click
ajax request is made to php page which returns json data
for each result in returned data additional ajax request is made
run function which makes additional ajax call
end for each
end click function
这一切都很好用,我想做的是在div中显示加载消息并禁用搜索按钮,然后当所有ajax请求完成后重新启用按钮并删除加载消息。
我的脚本在下面,此时按钮的禁用/重新显示几乎瞬间发生,我认为因为ajax调用是asyncronus,我如何重新启用按钮并在所有ajax请求后删除加载消息已完成并显示数据??
$('#advKeyBtn').live('click', function() {
$('#advKeyBtn').attr('disabled', 'disabled');
$('#searchStatus').html('<img src="../img/icons/loadinfo.gif" width="16" height="16" /> Searching Locations...');
$('#results').html(''); //clear existing contents
$('#borough_links').html(''); //clear existing contents
// handler for advance search button
var myUrl = 'getKeyBoroughs.php';
var myKeys = $('#keywords').val();
var myType = $('input[name=keyParams]:checked').val()
$.ajax({
url: myUrl,
data: "keys=" + myKeys +'&type='+myType,
type: "POST",
traditional: false,
dataType: 'json',
error: function(xhr, statusText, errorThrown){
// Work out what the error was and display the appropriate message
},
success: function(myData){
// data retrived ok
$.each(myData.boroughs, function( intIndex, objValue ){
//alert(myData.boroughs[intIndex].Borough_ID);
makeCSS(myData.boroughs[intIndex].Borough_ID);
getKeyLocations(myData.boroughs[intIndex].Borough_ID)
})
//$('#'+divId).append(myData)//construct location holders
}
});
$('#advKeyBtn').attr('disabled', '');
$('#searchStatus').html('Search Complete, click on an area to view locations');
});
以及从主要ajax调用的初始成功调用的函数
function getKeyLocations(id){
var myUrl = 'getKeyLocations.php';
var myBorough = id;
var myKeys = $('#keywords').val();
var myType = $('input[name=keyParams]:checked').val()
var divId = '#borough_'+ id;
$.ajax({
url: myUrl,
type: 'POST',
data: 'borough_id='+myBorough+'&keys='+myKeys,
error: function(xhr, statusText, errorThrown){
// Work out what the error was and display the appropriate message
},
success: function(myData){
$(divId).html(myData);
}
});
};
答案 0 :(得分:5)
您想要ajaxStart和ajaxStop,这里有一些显示加载屏幕的代码。这么漂亮的小衬里。
$('.loadingElement')
.ajaxStart(function() { this.show(); })
.ajaxStop(function() { this.hide(); });
根据您的具体用法,代码类似于
$('#advKeyBtn')
.ajaxStart(function() { this.attr('disabled', 'disabled'); })
.ajaxStop(function() { this.attr('disabled', ''); });
每当要发送Ajax请求时,jQuery都会检查是否 还有其他任何杰出的Ajax请求。如果没有 进度,jQuery触发ajaxStart事件。任何和所有处理程序 已经使用.ajaxStart()方法注册的是 这一次。
每当Ajax请求完成时,jQuery都会检查是否存在 任何其他杰出的Ajax请求。如果没有,jQuery会触发 ajaxStop事件。已注册的所有处理程序 此时执行.ajaxStop()方法。 ajaxStop 如果最后一个未完成的Ajax请求是,也会触发事件 通过在beforeSend回调函数中返回false来取消。
来自malsup,关于ajaxStop和ajaxComplete之间的差异:
ajaxStop是在未完成的ajax请求数时触发的 达到零。每次响应后都会触发ajaxComplete 接收。 ajaxComplete也传递了XHR和设置对象。
答案 1 :(得分:4)
您必须创建一个能够处理所有请求的函数。完成所有请求后,启用按钮并显示消息。
var ajaxLoading = {
_requestsInProcess: 0,
show: function () {
if (this._requestsInProcess == 0) {
$('#advKeyBtn').attr('disabled', 'disabled');
$('#searchStatus').html('<img src="../img/icons/loadinfo.gif" width="16" height="16" /> Searching Locations...');
}
this._requestsInProcess++;
},
hide: function () {
this._requestsInProcess--;
if (this._requestsInProcess == 0) {
$('#advKeyBtn').attr('disabled', '');
$('#searchStatus').html('Search Complete, click on an area to view locations');
}
}
};
现在,在所有ajax呼叫使用之前:
ajaxLoading.show()
在你所有的成功方法中使用:
ajaxLoading.hide()
希望这有帮助。
答案 2 :(得分:0)
是的,AJAX请求是异步的。一种解决方案是将计数器初始化为已发送的ajax请求的数量,然后在每个响应上减少计数器。当您达到0时,更新您的状态并重新启用。请记住,如果网络挂起,您可能希望在超时后自动重新启用。
答案 3 :(得分:0)
同意上述内容,购买我的建议是在超时或失败响应时递减计数器而不是使用计时器。
计数器将计算已完成的响应数(失败与否)。