Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bootstrap progress bar doesn't show progress?

I have a very long loop in JS (2M + iterations).
I would like to show some progress to the user.
For some reason the code hangs, and only shows progress when the loop is done.
What am I doing wrong?

CAREFUL BROWSER MIGHT GET STUCK, SET MAX ACCORDINGLY

var MAX = 100000;

function doIt(){        
      alert('start count :'+ MAX);
       for(i=0;i<MAX;i++){
          setTimeout(updateBar, 600 , i);
          console.log(i);
       }        
      alert('count ended');
}


function updateBar(idx) {
    var bar = document.getElementById('progress');
     bar.style.width = Math.floor(100 * idx / MAX) + '%';
}
body {padding: 50px;}
<link href="http://getbootstrap.com/2.3.2/assets/css/bootstrap.css" rel="stylesheet"/>

<button onclick="doIt()">Start counting</button>


<div class="progress">
    <div class="bar" id="progress"></div>
</div>
like image 789
JavaSheriff Avatar asked Mar 04 '26 00:03

JavaSheriff


1 Answers

Here is a possible solution, using a Web Worker:

enter image description here

worker-script.js (distinct context, distinct file)

// When this worker receives a message
self.addEventListener("message", onMessageReceive);

function onMessageReceive(e) {
  // Get the max value
  var max = e.data.value;
  // Run the calculation
  doIt(max);
}

function doIt(max) {
  // Send messages to the parent from time to time
  self.postMessage({ type: "start", value: max });
  for (i = 0; i < max; i++) {
    if (i % 5000 === 0) { // Every 5000 iterations - tweak this
      self.postMessage({ type: "progress", value: i });
    }
  }
  self.postMessage({ type: "end", value: max });
}

main.js (in your page)

var MAX = 20000000, // 20 millions, no problem
  worker = null;

// If workers are supported, create one by passing it the script url
if (window.Worker) {
  worker = new Worker("worker-script.js");
  document
    .getElementById("start-btn")
    .addEventListener("click", startWorker);
} else {
  alert("Workers are not supported in your browser.");
}

// To start the worker, send it the max value
function startWorker() {
  worker.postMessage({ value: MAX });
}

// When the worker sends a message back
worker.addEventListener("message", onMessageReceive);

function onMessageReceive(e) {
  var data = e.data;
  switch (data.type) {
    case "start":
      console.log(`start count: ${data.value}`);
      break;
    case "progress":
      updateBar(data.value);
      break;
    case "end":
      updateBar(data.value);
      console.log(`end count: ${data.value}`);
      break;
  }
}

function updateBar(idx) {
  var bar = document.getElementById("progress");
  bar.style.width = Math.floor((100 * idx) / MAX) + "%";
}

index.html

<button id="start-btn">Start counting</button>

<div class="progress">
  <div class="bar" id="progress"></div>
</div>

<script src="main.js"></script>
like image 150
blex Avatar answered Mar 06 '26 14:03

blex