我有一个进度条,我会在多次迭代的循环中更新它。
https://jsfiddle.net/k29qy0do/32/ (在单击start按钮之前打开控制台)
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();
});控制台会按照预期进行迭代更新。但是,进度条没有更新。
问题是浏览器窗口似乎“挂起”,直到循环结束。只更新控制台,而不更新进度条。
我已经尝试在几个地方添加setTimeout,如下所示。但这只会让事情变得更糟,因为在执行循环时,我甚至不会让控制台输出进度。
发布于 2015-07-27 21:31:47
好的,我在这个问题的答案中找到了一个解决方案:
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);
}
})();发布于 2015-07-28 01:11:55
让我们把这个分解成几个步骤
步骤1:清理HTML
假设您的问题的目的是了解如何使用进度条,而不是样式或标签(加载,请耐心等)。让我们只有进度条和开始按钮。
<div id='progressbar-outer' style="">
<div id='progressbar' style=""></div>
</div>
<button id="start_button">Start</button>第2步:样式
让我们让用户可以看到进度条
#progressbar-outer {
height:2em;
border:5px solid #000;
width:15em;
}
#progressbar {
width:0%;
background-color:#F00;
height:100%;
}步骤3:在该使用的地方使用setTimeout
在您的代码中,您已经使用setTimeout来设置进度条的值。但是,for循环仍处于活动状态。
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);
}
}使用setTimeout不会影响代码的其余部分。因此,UI一直被扣为人质,直到循环结束。尝试以下代码。
$('#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);
});预览
试试这个小提琴:https://jsfiddle.net/Ljc3b6rn/4/
发布于 2015-07-27 21:56:23
您真正需要的是一个异步循环,它允许浏览器在两次迭代之间更新DOM。
JSFiddle:http://jsfiddle.net/u5b6gr1w/
function delayedLoop(collection, delay, callback, context) {
context = context || null;
var i = 0,
nextInteration = function() {
if (i === collection.length) {
return;
}
callback.call(context, collection[i], i);
i++;
setTimeout(nextInteration, delay);
};
nextInteration();
}一些HTML:
<div class="progress-bar"><div style="width: 0"></div></div>CSS的一次飞溅:
.progress-bar {
border: 1px solid black;
background-color: #f0f0f0;
}
.progress-bar div {
background-color: red;
height: 1.25em;
}和一些JavaScript将东西连接在一起:
var progressBar = document.querySelector(".progress-bar div"),
items = [1,2,3,4,5,6,7,8,9,10];
delayedLoop(items, 500, function(item, index) {
var width = (item / items.length * 100) + "%";
progressBar.style.width = width;
progressBar.innerHTML = width;
});https://stackoverflow.com/questions/30987218
复制相似问题