So is there any way to run the for loop and generate the progress bar without cost more time?
В основном нет (смотрите ниже, почему «в основном»), вы должны дать обратно в браузер (например, с помощью setTimeout
или setInterval
), поэтому он может обновить отображение страницы, и это будет действительно увеличить количество времени цикла. Теперь, как правило, если вы используете тайм-аут 0
, браузеры перезвонят вам между 5 и 10 миллисекундами. Так называйте это 10 мс. В вашем цикле 1000 циклов вы можете получить каждые 100 циклов (например, 10 обновлений прогресса), которые добавили бы только 100 мс к общему времени.
FWIW, который выглядит следующим образом (скажем, это массив вы циклически):
function loop(array, batchSize, callback) {
var index = 0;
doWork();
function doWork() {
var limit = Math.min(array.length, index + batchSize);
while (index < limit) {
// Do something with array[index]
}
if (limit < max) {
setTimeout(doWork, 0);
}
else {
callback(); // Done
}
}
}
Использование:
loop(someArray, 100, function() {
// Done
});
Почему "в основном" нет: На some browsers (не, в частности, IE9 или ранее), для некоторых задач вы можете использовать web workers. Веб-рабочий - это изолированный поток JavaScript, отдельно от основного потока JavaScript, который работает в фоновом режиме. Эти два потока обмениваются сообщениями друг с другом.
Таким образом, вы можете запустить веб-работника, передать ему работу и опубликовать сообщения, чтобы обновить индикатор выполнения. This article дает основы веб-работников, если вы хотите пойти по этому маршруту.
Для чего это стоит, это выглядит примерно так:
основного документа и сценария:
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>Progress</title>
<style type="text/css">
body, html {
height: 100%;
}
body {
font-family: sans-serif;
}
</style>
</head>
<body>
<div id="progress"><em>(Click to start)</em></div>
<script>
(function() {
var div = document.getElementById("progress");
var counter = new Worker("counter.js");
div.addEventListener("click", run);
counter.addEventListener("message", function(event) {
div.innerHTML = "Counter so far: " + event.data.counter;
});
function run() {
div.removeEventListener("click", run);
counter.postMessage({ max: 10000000 });
}
})();
</script>
</body>
</html>
counter.js
веб-рабочий сценарий (они всегда отдельные файлы):
self.addEventListener("message", function(event) {
var max;
var counter;
max = event.data && event.data.max || 100000;
for (counter = 0; counter < max; ++counter) {
if (counter % 1000 === 0) {
self.postMessage({counter: counter});
}
}
self.postMessage({counter: counter});
});
вам потребуется время, добавленное setinterval. запуск цикла 1000 раз настолько быстр, что вы не увидите, что индикатор выполнения действительно продвигается ... –
@Bartdude, что если цикл займет более половины миниатюры? Тогда это имеет смысл. – Kimmi