1

I'm making a game with world generation and I want to display the generation progress on screen. Even with the for loop inside of an async function it stops all other code outside of the function to run the loop.

I've tried a forEach loop which had the same issue and had worse performance.

async function genWorld(){
  setupWorld();
}

async function setupWorld(){
  let size = worldSize.width * worldSize.height;
  let up = size/100;
  let check = 0;
    for(i = 0; i < worldSize.width; i++){
        for(z = 0; z < worldSize.height; z++){
            check++;
            if(check == up){
                console.log("test");
                check = 0;
                worldGenProgress.full++;
            }
        }
    }
}

I expect the progress bar to graphically update inline with the for loops instead of jumping to 100% once they finish.

  • 1
    You might want to read a bit up on Javascript not being multi-threaded in the sense of processing functions. Putting async doesn't magically make it multi-threaded (and thus not freeze up your other code). You can use workers (web workers) to possibly parallelize your task. – Cody G Apr 21 '19 at 22:44
  • 1
    Not a bad question, didn't deserve a down-vote. This might help you: https://lavrton.com/javascript-loops-how-to-handle-async-await-6252dd3c795/ – Alicia Sykes Apr 21 '19 at 22:47

1 Answers1

0

The for loop adds up the value of check to the value size. That is not exactly going to take a while. And there are no promises in the loop, so it is still blocking.

function mandelaEffect() {
    return new Promise( (MyThen, MyCatch) => {
        setTimeout(MyThen);
        return "Things on the page may have changed? Or maybe not?";
    })
}

async function setupWorld(){
  let size = worldSize.width * worldSize.height;
  let up = size/100;
  let check = 0;
    for(i = 0; i < worldSize.width; i++){
        for(z = 0; z < worldSize.height; z++){
            check++;
            await mandelaEffect(100); // this could be 1 just to allow browser events.
            if(check == up){
                console.log("test");
                check = 0;
                worldGenProgress.full++;
            }
        }
    }
}

The magic happens at the await within the loop. At the await, an async function waits, (with browser events unblocked), and when the promise from the await is answered resumes at the point it waited.

So while and for loops become usable without blocking the page.

Edited -> (typo) to => arrow function.

Wayne
  • 4,760
  • 1
  • 24
  • 24
  • This doesn't seem to work, I'm getting the same result. Also I'm guessing that's coffeescript? – ArtificialLegacy Apr 22 '19 at 00:20
  • Edited -> (typo) to => arrow function. My bad I'm using multiple systems on the desk and I had to type in the promise function. It is suppose to have been a simple arrow function, commonly known as delay. But I prefer the name Mandela effect. – Wayne Apr 22 '19 at 00:34