I have a progress bar that I update in a loop of many iterations.
https://jsfiddle.net/k29qy0do/32/ (open the console before you click the start button)
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'),
/** 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);
}
};
});
$('#start_button').on('click', function () {
var iterations = 1000000000;
progressbar.progress_max = iterations;
var loop = function () {
for (var i = 1; i <= iterations; i++) {
if (iterations % i === 100) {
progressbar.set(i); //only updates the progressbar in the last iteration
//progressbar.fn_wrap(i); //even worse, since no output to the console is produced
}
}
}
//setTimeout(loop, 0);
loop();
});
The console is updated iteratively as expected. However, the progressbar is not updating.
The problem is that the browser window seems to 'hang' until the loop finishes. Only the console is updated, not the progressbar.
I have tried to add the setTimeout, as suggested below, in several places. But that just makes things worse, because I then do not even get the console to output the progress while executing the loop.
Okay, I found a solution in the answer to this question:
Javascript: How to update a progress bar in a 'for' loop
var i = 0;
(function loop() {
i++;
if (iterations % i === 100) {
progressbar.set(i); //updates the progressbar, even in loop
}
if (i < iterations) {
setTimeout(loop, 0);
}
})();
My solution: https://jsfiddle.net/ccvs4rer/3/
Lets break this down to steps
Assuming the purpose of your question is to understand how to work the progress bar and not the styles or the labels (loading, please be patient, etc.). Lets just have the progress bar and the start button.
<div id='progressbar-outer' style="">
<div id='progressbar' style=""></div>
</div>
<button id="start_button">Start</button>
Lets make the progress bar visible to the user
#progressbar-outer {
height:2em;
border:5px solid #000;
width:15em;
}
#progressbar {
width:0%;
background-color:#F00;
height:100%;
}
setTimeout
where it belongsIn your code, you have used setTimeout
to set the value of your progress bar. However, the for
loop is still active.
for (var i = 1; i <= iterations; i++) {
if (iterations % i === 100) {
progressbar.set(i); //only updates the progressbar in the last iteration
//progressbar.fn_wrap(i); //even worse, since no output to the console is produced
//setTimeout(function() {
// progressbar.set(i);
//}, 0);
}
}
The use of setTimeout
does not affect the rest of the code. Hence, the UI was held hostage till the loop ended. Try the following code.
$('#start_button').on('click', function () {
var iterations = 100;
progressbar.progress_max = iterations;
var loop = function (value) {
progressbar.set(value);
if (value < iterations) setTimeout(function () {
loop(value + 1)
}, 30);
else $('#progressbar').css('background-color', '#0F0');
}
loop(1);
});
Try this fiddle: https://jsfiddle.net/Ljc3b6rn/4/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With