1

In Javascript, when you write a piece of code like the one below, it seems like the computer will first complete the entire loop 100 000 times (which can take a second or two) and THEN dump all 100 000 lines in the console in one shot. How can I make it so that the computer will update the console one line at a time, with each pass thru the loop?

To clarify, I would like to, in effect, be able to see what the computer is doing AS it is doing it, and not once it has finished doing it.

for (var i = 1; i <= 100000; i++) {
  console.log(i);
}
snowfrogdev
  • 5,963
  • 3
  • 31
  • 58
  • 2
    In what environment? Javascript runs in a lot of different places with a lot of different implementations of `console.log` – Dark Falcon Dec 28 '16 at 16:57
  • 1
    Open chrome dev tools, switch to console, paste that code in, ???, profit! – imjared Dec 28 '16 at 16:58
  • 1
    I have a feeling that you're working in an environment that has some sort of start-up delay. Even if the loop runs entirely before any logging is done, a mere 100,000 iterations shouldn't take a detectable amount of time... – Gershom Maes Dec 28 '16 at 17:06
  • @DarkFalcon In JSfiddle or codepen for example, running on Chrome browser. – snowfrogdev Dec 28 '16 at 17:08
  • @GershomMaes You are right, I was giving the 100 000 for loop as a simple example. I'm more interested in cases where I'm running computation and memory intensive algorithms (say a minimax algorithm) that runs a recursive function hundreds of thousands of times and may take a few seconds to run its course. Still, if you run the code snippet I have included, you will notice a delay befor the output. – snowfrogdev Dec 28 '16 at 17:11
  • 2
    The delay in the code you posted is due to stackoverflow's embedded script running environment. Stackoverflow's script runner is immediately calling console.log, but because of the synchronous nature of the browser it needs to allow the entire loop to finish before it can display any output. – Gershom Maes Dec 28 '16 at 17:43

5 Answers5

3

Browsers run script synchronously. If you want the page to update as a long task is running, you need to break your long-running synchronous code up into pieces, and relinquish control to the browser between the processing of these pieces. This means that you need to deal with breaking a series of tasks into chunks, and controlling the delays which return control to the browser.

Here's a snippet which provides a method that allows you to do exactly this! You'll notice the performance is still not great, but I'm quite sure this is due to the slowness of stackoverflow's embedded script runner's implementation of console.log. Try using this code in the browser's actual console - the performance is great!

function doHeavyTask(params) {
  var totalMillisAllotted = params.totalMillisAllotted;
  var totalTasks = params.totalTasks;
  var tasksPerTick = params.tasksPerTick;
  var tasksCompleted = 0;
  var totalTicks = Math.ceil(totalTasks / tasksPerTick);
  var interval = null;
        
  if (totalTicks === 0) return;
  
  var doTick = function() {
    var totalByEndOfTick = Math.min(tasksCompleted + tasksPerTick, totalTasks);
  
    do {
      params.task(tasksCompleted++);
    } while(tasksCompleted < totalByEndOfTick);
     
    if (tasksCompleted >= totalTasks) clearInterval(interval);
  };
  
  // Tick once immediately, and then as many times as needed using setInterval
  doTick();
  if (totalTicks > 1) interval = setInterval(doTick, totalMillisAllotted / totalTicks);
}

// Do 10,000 console.logs, in chunks of 100, within 5 seconds
doHeavyTask({
  totalMillisAllotted: 5 * 1000,
  totalTasks: 10000,
  tasksPerTick: 100,
  task: function(n) { console.log(n + 1); }
});
Gershom Maes
  • 7,358
  • 2
  • 35
  • 55
  • Sorry, how to do this in a slow mode? By slow mode I mean only 1 task per 3-5 seconds. Cause I try to change those parameters but I always ended up wrong. Probably you could enlight me. – Fahmi Jabbar May 13 '21 at 15:48
  • 1
    For a 5 second delay you need to start off knowing how many tasks you want done; say you want 100. Then set `totalTasks` to 100, set `tasksPerTick` to 1, and set `totalMillisAllotted` to `100 * 5000` (five seconds per task). – Gershom Maes May 13 '21 at 16:31
0

If you want a smoother output, I would suggest avoiding the for loop, and instead use requestAnimationFrame which will manage when to print out the results.

var counter = 0;
var max = 100000;
function myPrint(){
    if(counter < max){
        console.log(counter++);
        requestAnimationFrame(myPrint);
    }
}
myPrint();
bobjoe
  • 673
  • 6
  • 11
0

for (let i = 1; i <= 10; i++) {
  //console.log(i);
  setTimeout(function(){console.log(i)},i*1000);
}

here is how you can delay your console. use setTimeout to check the value of console.log value after 1sec(1000ms).

let allows you to declare variables that are limited in scope to the block, statement, or expression on which it is used. This is unlike the var keyword, which defines a variable globally, or locally to an entire function regardless of block scope.

jindhk
  • 61
  • 6
0

One could feed an array of Promises to an Observable in order to achieve the desired outcome. Promises are now native to JavaScript and you can get the Observable from the RxJS library.

Here is an example:

const array = [];

// This could also be a for of loop or a .map() function
for (let i = 0; i <= 25; i++) {
  const promise = new Promise((resolve) => {

    // This could be any synchronous or asynchronous code
    setTimeout(() => {
      resolve(i);
    }, 1000 * i);
  });

  array.push(promise);
}

var observable = Rx.Observable.from(array);

observable.subscribe((promise) => {
  promise.then(result => console.log(result));
});
<script src="https://unpkg.com/rxjs/bundles/Rx.min.js"></script>
snowfrogdev
  • 5,963
  • 3
  • 31
  • 58
-2

Your statement is not valid. JavaScript handles the for loop synchronously.

Please check the following question: JavaScript, Node.js: is Array.forEach asynchronous?

Community
  • 1
  • 1
Tome Pejoski
  • 1,582
  • 2
  • 10
  • 34
  • 1
    This is not really related to the question. The question is more along the lines of whether `console.log` can be made to output immediately rather than after the loop has completed. The answer is that it depends on the environment. For example, with node.js, yes it can: http://stackoverflow.com/a/27900423/2101267 – Dark Falcon Dec 28 '16 at 17:04
  • @DarkFalcon console.log is logging immediately. – Tome Pejoski Dec 28 '16 at 17:05