我试图拉回几组统计数据并在每组数据均已加载到DOM后显示进度消息。
我正在尝试使用多个deferreds以及setTimeout函数来管理对用户的响应。
我开始调用一个函数来显示我的加载消息。然后,我使用AJAX检索数据。然后,成功函数将遍历数据集和:
$(function() {
displayMyWaiter('Fetching month end statistics for all pitches....');
$.ajax ( {
url: '../../ajax/stats.php',
method: 'GET',
data: {mode: 'all statistics for ent', statEntity: 'pitch', statType: 'total', statFilter: 'distinct'},
dataType: 'json',
type: 'POST',
success: function(statGroup){
console.log(statGroup);
var promises = [];
for (var i in statGroup) {
var stat = statGroup[i];
console.log(stat);
var def = $.Deferred();
$.when( loadDomElement(stat) ).done(function() {
console.log( "hello" );
def.resolve();
promises.push(def);
});
};
$.when.apply($, promises).done(function() {
hideMyWaiter("slide");
});
}
});
});
loadDomElement函数将当前状态作为参数传递给它,并返回一个Promise。它实际上是在我的页面上添加了一个html块。然后,它调用loadStat函数,该函数还返回一个promise-它解决了loadDomElement函数中的延迟问题。代码如下:
function loadDomElement(stat) {
var dfd = $.Deferred();
var statPanelID = 'stat_block_' + stat.code;
$('#stats').append( '<div id="' + statPanelID + '"></div>' );
$.when( loadStat(statPanelID, stat) ).done(function() {
dfd.resolve();
});
return dfd.promise()
}
loadStat函数从创建一个externalDef延迟变量开始。然后,它调用我的函数来更新Loading块中的消息。这将返回一个承诺:
function updateMyWaiter(str) {
var text = "<li class='waiter-item'>" + str + "</li>"
var dfd = $.Deferred();
setTimeout(function(){
$('.busyText').append(text);
dfd.resolve();
}, 3000);
return dfd.promise();
}
当返回承诺时,它随后调用我的面板函数(该函数也返回一个承诺)并使用我的自定义插件将统计数据加载到页面上(在“加载”消息之后)。该函数如下所示:
function loadStat(statPanelID, stat) {
console.log("Now create stats for " + stat.code + ": " + stat.desc + " and place it in this block: " + statPanelID);
var outerDef = $.Deferred();
$.when( updateMyWaiter("Loading stats for " + stat.desc + "( code: " + stat.code + ")") ).done(function() {
var panel = function() {
var d = $.Deferred();
var panelTitle = (stat.desc === null ? 'Pitch ' + stat.code : stat.desc);
var statPluginID = 'stat_' + stat.code;
$("#" + statPanelID).panIt({
allowScrolling: false,
header: {
title: panelTitle
},
body: {
content: '<div id="' + statPluginID + '">Position stat plugin for ' + stat.desc + ' here.</div>',
height: '700'
},
onLoaded: function() {
$.when ( $('#' + statPluginID).stats({ // dom ID for stat plugin
statEntity: 'pitch',
statEntityID: stat.code,
statType: 'total',
statPeriod: null,
chartType: 'line',
chartTitle: 'Pitch stats for: ' + stat.desc,
activeTab: 'chart',
clickOptions: {
enabled: false
},
chartHeight: 700,
table: {
headers: [
{ name: 'Month', data: 'month' },
{ name: 'BF', data: 'bf' },
{ name: 'New', data: 'new_mem' },
{ name: 'Trn In', data: 'tra_in' },
{ name: 'Trn Out', data: 'tra_out' },
{ name: 'Lapsed', data: 'lapsed' },
{ name: 'CF', data: 'cf' },
{ name: 'Balance', data: 'balance'}
],
hasSelect: false,
search: false
}
})).done (function(result) {
d.resolve ('Pitch stats: ' + result);
});
}
});
return d.promise();
};
$.when ( panel() ).done (function(result) {
console.log(result);
outerDef.resolve(result);
});
});
return outerDef.promise();
}
我本质上希望应用程序以我最初的消息开头:“正在获取所有音调的月末统计信息...。”,然后对于每个统计信息,它都应该使用anotehr行更新加载消息,该行指出现在正在加载哪个统计信息。加载所有统计信息后,应隐藏加载消息。
但是发生的是,我收到了初始消息,该消息仅在隐藏之前显示一秒钟。然后,应用程序继续将数据加载到DOM。
答案 0 :(得分:0)
我在另一个日志中找到了答案:click here
我对代码进行了如下调整:
$(function() {
displayMyWaiter('Fetching month end statistics for all pitches....');
$.ajax ( {
url: '../../ajax/stats.php',
method: 'GET',
data: {mode: 'all statistics for ent', statEntity: 'pitch', statType: 'total', statFilter: 'distinct'},
dataType: 'json',
type: 'POST',
success: function(statGroup){
handlePitchData(statGroup, 0);
}
});
});
function handlePitchData(statGroup, i) {
if(i<statGroup.length){
var stat = statGroup[i];
console.log(statGroup[i]);
$.when( loadDomElement(stat) ).done(function() {
handlePitchData(statGroup, i+1);
});
} else {
hideMyWaiter("slide");
}
}
function loadDomElement(stat) {
var dfd = $.Deferred();
var statPanelID = 'stat_block_' + stat.code;
$('#stats').append( '<div id="' + statPanelID + '"></div>' );
$.when( updateMyWaiter("Loading stats for " + stat.desc), loadStat(statPanelID, stat) ).done(function() {
dfd.resolve();;
});
return dfd.promise();
}
function loadStat(statPanelID, stat) {
console.log("Now create stats for " + stat.code + ": " + stat.desc + " and place it in this block: " + statPanelID);
var outerDef = $.Deferred();
var panel = function() {
var d = $.Deferred();
var panelTitle = (stat.desc === null ? 'Pitch ' + stat.code : stat.desc);
var statPluginID = 'stat_' + stat.code;
$("#" + statPanelID).panIt({
allowScrolling: false,
header: {
title: panelTitle
},
body: {
content: '<div id="' + statPluginID + '">Position stat plugin for ' + stat.desc + ' here.</div>',
height: '700'
},
onLoaded: function() {
$.when ( $('#' + statPluginID).stats({ // dom ID for stat plugin
statEntity: 'pitch',
statEntityID: stat.code,
statType: 'total',
statPeriod: null,
chartType: 'line',
chartTitle: 'Pitch stats for: ' + stat.desc,
activeTab: 'chart',
clickOptions: {
enabled: false
},
chartHeight: 700,
table: {
headers: [
{ name: 'Month', data: 'month' },
{ name: 'BF', data: 'bf' },
{ name: 'New', data: 'new_mem' },
{ name: 'Trn In', data: 'tra_in' },
{ name: 'Trn Out', data: 'tra_out' },
{ name: 'Lapsed', data: 'lapsed' },
{ name: 'CF', data: 'cf' },
{ name: 'Balance', data: 'balance'}
],
hasSelect: false,
search: false
}
})).done (function(result) {
d.resolve ('Pitch stats: ' + result);
});
}
});
return d.promise();
};
$.when ( panel() ).done (function(result) {
console.log(result);
outerDef.resolve(result);
});
return outerDef.promise();
}
简而言之,我使用了递归方法。