最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - progress bar in for loop - Stack Overflow

programmeradmin0浏览0评论

I need a progress bar in a for loop in javascript

for(index=0; index < 1000; index++){
    // set progress bar value to  index/1000 * 100 + '%'
}

I notice we can put it in a setInterval function, but it will cost more time to run the for loop.

So is there any way to run the for loop and generate the progress bar without cost more time?

I need a progress bar in a for loop in javascript

for(index=0; index < 1000; index++){
    // set progress bar value to  index/1000 * 100 + '%'
}

I notice we can put it in a setInterval function, but it will cost more time to run the for loop.

So is there any way to run the for loop and generate the progress bar without cost more time?

Share Improve this question edited Oct 17, 2020 at 18:01 HK boy 1,40611 gold badges19 silver badges26 bronze badges asked Jul 9, 2013 at 15:40 KimmiKimmi 6012 gold badges8 silver badges22 bronze badges 2
  • you need that time added by a setinterval. running a loop 1000 times is so quick you won't see the progress bar actually progress... – Laurent S. Commented Jul 9, 2013 at 15:43
  • @Bartdude what if the loop take more than half a miniute? Then it make sense. – Kimmi Commented Jul 9, 2013 at 17:28
Add a ment  | 

2 Answers 2

Reset to default 9

So is there any way to run the for loop and generate the progress bar without cost more time?

Mostly no (see below for why "mostly"), you have to yield back to the browser (e.g., via setTimeout or setInterval) so it can update the page display, and that will indeed increase the amount of time the loop runs. Now, typically if you use a timeout of 0, browsers will call you back in between 5 and 10 milliseconds. So call it 10ms. In your 1,000-cycle loop, you might yield every 100 cycles (e.g., 10 progress updates), which would only add 100ms or so to the total time.

FWIW, that looks like this (let's say it's an array you're looping through):

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
        }
    }
}

Use:

loop(someArray, 100, function() {
    // Done
});

Why "mostly" no: On some browsers (not, notably, IE9 or earlier), for some tasks, you could use web workers. A web worker is an isolated JavaScript thread, separate from the main JavaScript thread, which runs in the background. The two threads municate by posting messages to each other.

So you could fire up a web worker, hand it the work, and have it post you messages to update your progress bar. This article gives the basics of web workers, if you want to go that route.

For what it's worth, it looks something like this:

Main document and script:

<!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 web-worker script (they're always separate files):

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});
});

You can use async/await and Promise + setTimeout as below Plaese remember that in case You would like receive return value You have to use the await iterate() (from async function or console)

document.body.innerHTML="<div id='id'>test</div>"
iterate()
    async function iterate() {

        function delay(ms=0000,foo=null) {
            return new Promise((resolve, reject) => {
                setTimeout(() => {
                    resolve((foo && foo()));
                }, ms); // 5 sekund
            });
        }


        for (i=0;i<1000;i++) {
            await delay(0);
            document.getElementById("id").innerText=i;
        }
        return "END"
    }

发布评论

评论列表(0)

  1. 暂无评论