我有一个使用kendoGrid的应用程序,我将它们保存到我们的数据库后更新所选行。
有时我们有1000多行,所以我必须对行进行分区,以免使应用程序陷入困境。这需要相当长的时间,所以我想显示一个进度条,以帮助用户查看更新的进度。
问题是进度条在每次迭代中都没有更新。当我逐步使用chrome调试器时,我可以看到进度条更新。但是当我实时运行脚本时没有任何反应。
HTML
<div id="progressbar-wrapper">
<div id="progressbar-outer" style="display: table;margin: 0 auto;background-color: #FFFFFF;border: 5px solid #000000;width: 50%;height: 30px;opacity: 1;z-index: 9998">
<div id="progressbar" style="float:left;width: 0;height: 30px;background-color:#000000;border: 0;opacity: 1;z-index: 99999">
</div>
</div>
<div id="loading-animation" style="position: fixed;top: 150px;left: 0;height: 120px;width: 100%;font-size: 100px;line-height: 120px;text-align: center;color: #000000;z-index: 9999;">
...SAVING...<br /><small>Saving Lines</small>
</div>
</div>
JAVASCRIPT
var progressbar = {};
$(function () {
progressbar = {
/** initial progress */
progress: 0,
/** maximum width of progressbar */
progress_max: 0,
/** The inner element of the progressbar (filled box). */
$progress_bar: $('#progressbar'),
/** Method to set the progressbar.
*/
set: function (num) {
if (this.progress_max && num) {
this.progress = num / this.progress_max * 100;
console.log('percent: ' + this.progress + '% - ' + num + '/' + this.progress_max);
this.$progress_bar.width(String(this.progress) + '%');
}
},
fn_wrap: function (num) {
setTimeout(function () {
this.set(num);
}, 0);
}
};
});
var processedPartitions = 0;
var partitions = saveData.partition(30); //saveData is the selected saved rows
//Iterate through partitions
for (var i = 0; i < partitions.length; i++) {
var urlForWindow = "/Data/Save/";
$.ajax({
url: urlForWindow,
type: "POST",
dataType: 'json',
contentType: 'application/json; charset=utf-8',
data: JSON.stringify(partitions[i]),
async: true,
complete: function () {
processedPartitions++;
if (processedPartitions === partitions.length) {
//PROGRESS BAR (DOESNT WORK, Doesnt show or update the progressbar in real time) ==========================================
//Get the full number of rows getting updated.
var iterations = 0;
for (var i = 0; i < partitions.length; i++) {
iterations = iterations + partitions[i].length;
}
//add total number of records to update as the iterations
progressbar.progress_max = iterations;
//make the progress bar visable before updating //does not show
$("#progressbar-wrapper").css("display", "block");
//start counter of rows updated
var recordsUpdated = 0;
//begin update loop
var mainGrid = $("#mainGrid").data("kendoGrid");
$.each(mainGrid.dataSource.data(), function () {
if (this.RowSelected === true) {
for (var i = 0; i < partitions.length; i++) {
for (var j = 0; j < partitions[i].length; j++) {
var row = mainGrid.dataSource.getByUid(this.uid);
row.set("RowSelected", "false");
row.set("dirty", "false");
//after update iterate recordsupdated
recordsUpdated++;
//update the progress bar if not complete //doesnt update in realtime
if (iterations >= recordsUpdated) {
progressbar.set(recordsUpdated);
}
}
}
}
});
//turn off progressbar after complete // never shows in realtime, never shown closing
$("#progressbar-wrapper").css("display", "none");
//Success message
alert("Saved");
}
},
error: function (jqXHR, textStatus, errorThrown) {
alert(jqXHR.resonseText);
}
});
}
逐步逐步执行代码,我可以看到一切正常。但是在实时运行时。进度条永远不会显示。就像整个页面冻结一样。
答案 0 :(得分:0)
由于javascript是单线程的,因此无法同时执行多项任务。然而,HTML5引入了Web工作者,我相信您可以通过Web worker实现您的需求,以便后台线程将用于服务器交互,主线程将为UI更新备用。
答案 1 :(得分:0)
所以我想通了。只需将两个过程分开。 ajax完成并将完整标志发送到以下方法以使用事件循环更新网格。
//Get the number of saved data rows. That = total iteration
var iterations = saveData.length; //get data
var processedPartitions = 0;
var partitions = saveData.partition(30); partition data
//write buyer to Database First (Quickest method)
for (var p = 0; p < partitions.length; p++) {
var urlForWindow = "/Data/Save/";
$.ajax({
url: urlForWindow,
type: "POST",
dataType: 'json',
contentType: 'application/json; charset=utf-8',
data: JSON.stringify(partitions[p]),
async: true,
beforeSend: function () {
},
success: function (result) {
successComplete = 1; //1 means success
},
complete: function () {
processedPartitions++;
//check if all partitions processed
if (processedPartitions === partitions.length) {
successComplete = successComplete + 1; //2 means successful completion
}
},
error: function (jqXHR, textStatus, errorThrown) {
alert(jqXHR.resonseText); //0 means error
}
});
}
//PROGRESS BAR ================================================
//max progress bar
progressbar.progress_max = iterations;
var mainGrid = $("#mainGrid").data("kendoGrid");
var i = 0; //partition #
var j = 0; //line #
var linesUpdated = 0; //update complete #
//make the progress bar visable before updating
$("#progressbar-wrapper").css("display", "block");
//then loop through update grid methods
(function innerloop() {
try {
//If end
var testPart = (partitions[i].length - 1); //30 but starts at 0
} catch (err) {
//exit loop
return;
}
//Get the length of the partition
var thisPartitionLength = (partitions[i].length - 1); //30 but starts at 0
if (thisPartitionLength >= j && successComplete === 2) {
$.each(mainGrid.dataSource.data(),
function () {
if (this.RowSelected === true) {
//get id
var row = mainGrid.dataSource.getByUid(this.uid);
//unselect and turn off dirty
row.set("RowSelected", "false");
row.set("dirty", "false");
linesUpdated++;
}
});
//update line #
j++;
//update progressbar
progressbar.set(linesUpdated);
}
if (j <= thisPartitionLength) {
//loop if not complete with partition
setTimeout(innerloop, 0);
} else {
if (j > thisPartitionLength) {
//if end of partition reset the line # and increase partition # and continue loop
i++;
j = 0;
setTimeout(innerloop, 0);
}
//on complete
if (linesUpdated === iterations) {
//Success message
alert("Saved");
}
}
})();
<强>更新强>
唉!!这在IE11中不起作用!