【发布时间】:2019-08-19 09:10:00
【问题描述】:
我正试图在每组数据加载到 DOM 后拉回几组统计数据并显示进度消息。
我正在尝试使用多个延迟和 setTimeout 函数来管理对用户的响应。
我开始调用一个函数来显示我的加载消息。然后我使用 AJAX 来检索数据。然后成功函数循环遍历数据集并:
- 在统计变量中定义当前数据集
- 调用 loadDomElement 函数(参见下面的解释),该函数返回一个承诺
- 将返回的 Promise 推送到我的 Promise 数组中
- 使用 .apply 函数传递 Promise 数组,当所有 Promise 完成后,它隐藏加载块以显示所有已在后台加载的元素。
$(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 函数将当前状态作为参数传递给它并返回一个承诺。它本质上是在我的页面上附加了一个 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 函数首先创建一个 outerDef 延迟变量。然后它调用我的函数来更新 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();
}
当 promise 返回时,它会调用我的面板函数(它也返回一个 promise)并使用我的自定义插件将统计数据加载到页面上(在 Loading 消息后面)。函数如下所示:
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。
【问题讨论】:
-
你需要使用promise对象javascript.info/promise-basics
-
@Taplar 哎呀,我被委派和延期混在一起了,需要眼镜吗????
-
谢谢@Hogan。只是为了澄清一下,您是说这不能使用 JQuery deferred 来完成,还是只是说 Promise 更容易或更好地使用?谢谢
标签: jquery ajax jquery-deferred