Progress Bar with Nested For-loops

柔情痞子 提交于 2019-12-12 03:48:12

问题


Looping over two different arrays, both for-loops nested within each other asynchronously (as chunks and setTimeout sourced from here), and trying to use the progress bar example from W3Schools here (the Label one).

The sourced (slightly modified for a 'done' callback) asynchronous function:

function loopAsync(array, fn, done, chunk, context) {
    context = context || window;
    chunk = chunk || 10;
    var index = 0;

    function doChunk() {
        var cnt = chunk;
        while (cnt-- && index < array.length) {
            // callback called with args (value, index, array)
            fn.call(context, array[index], index, array);
            ++index;
            //console.log("index is " + index);
            progressBar(index);
        }
        if (index < array.length) {
            // set Timeout for async iteration
            setTimeout(doChunk, 1);
        } else {
            done && done();
        }
    }
    doChunk();
}

Regardless of being asnychronous, these are the same problems even with a normal for-loop:

  1. The W3School example is using setInterval, which is inaccurate since the for-loops may already finish processing before setInterval is.

  2. There are two nested for-loops, so instead of tracking the progress of (for example) i in for (var i=0...), it needs to track the first loop * the second loop for accuracy (as to not appear stopped - especially because the second loop will likely have a larger array length than the first).

For example:

Asynchronously using the linked example above:

loopAsync(arr1, function (item1) {
    loopAsync(arr2, function (item2) {
        //Comparing or processing item1 with item2
    });
}, doNext);

Or, basically the same without asynchronous looping:

for (var item1 = 0; item1 < arr1.length; ++item1) {
    for (var item2 = 0; item2 < arr2.length; ++item2) {
        //Doing things... need to track progress of both?
    }
}
  1. Needs to be generic, able to be used in any nested (or non-nested) for-loop operation.

How should these problems be addressed, preferably without jquery?


回答1:


i think thats just need basic increment. you can use something like this:

function progress(total) {
  this.inc = (total !== 0? this.inc || 0: -1) + 1;
  var percentage = Math.floor(this.inc / total * 100);
  document.write('Processing ' + this.inc + '/' + total + ' ' + percentage + '%<br/>');
}

var arr1 = [1,2,3,4,5];
var arr2 = [1,2,3,4,5,6,7,8,9];

for (var item1 = 0; item1 < arr1.length; ++item1) {
  for (var item2 = 0; item2 < arr2.length; ++item2) {
      progress(arr1.length * arr2.length);
  }
}

// reseting counter
progress(0);

// count another progress
var arr3 = [1,2,3];

for (var item1 = 0; item1 < arr1.length; ++item1) {
  for (var item2 = 0; item2 < arr2.length; ++item2) {
    for (var item3 = 0; item3 < arr3.length; ++item3) {
        progress(arr1.length * arr2.length * arr3.length);
    }
  }
}

another example with random execution time (use promise to doing async process)

function progress(total) {
  this.inc = (total !== 0? this.inc || 0: -1) + 1;
  document.getElementById('progress').innerHTML = 'Processing ' + Math.floor(this.inc / total * 100) + '%';
}

function processing_something(callback) {
  setTimeout(function(){
    callback();
    //execution between 1 to 10 secs
  }, Math.floor(Math.random() * 10) * 1000);
}

var arr1 = [1,2,3,4,5];
var arr2 = [1,2,3,4,5,6,7,8,9];

for (var item1 = 0; item1 < arr1.length; ++item1) {
  for (var item2 = 0; item2 < arr2.length; ++item2) {
      new Promise(function(resolve) {
      	//do something that require time
        processing_something(resolve);
      }).then(function(){
      	 progress(arr1.length * arr2.length);
      });
  }
}
<div id="progress"></div>


来源:https://stackoverflow.com/questions/42335488/progress-bar-with-nested-for-loops

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!