kendoGridを使用しているアプリケーションで、選択した行をdbに保存した後に更新します。ループ内のループ内のループ内のループ内でループ内のプログレスバーを更新する方法
私たちは時には1000以上の行を持っているので、アプリケーションを動かさないために行を分割する必要があります。これはかなり長い時間がかかりますので、ユーザーが更新プログラムの進捗状況を確認できるようにプログレスバーを表示したかったのです。
問題は、各繰り返しで進行状況バーが更新されないことです。私はクロムデバッガを使用してステップを進めるので、私はプログレスバーの更新を見ることができます。しかし、私はリアルタイムでスクリプトを実行すると何も起こりません。
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);
}
});
}
だから私はすべてが動作することを確認することができ、線でコード行をステップ実行。しかし、リアルタイムで実行しているとき。プログレスバーは決して表示されません。そのページ全体が凍っているようです。
Ajaxをループするためにintervalまたはtimeoutを使用しないでください。 ajax呼び出しの成功または完了から次のajaxを実行する関数を呼び出します。そこからもsetTimeoutを使うことができますが、ループ内にajaxをラップしません。 – mplungjan
ブラウザはシングルスレッドです。バーはjsが停止するまで更新されません。 –
ジョナスが言ったこと。実際に理解できる価値のあるものは、イベントループです:https://www.youtube.com/watch?v=8aGhZQkoFbQ – Xeraqu