1

I am attempting to use a callback to create an asynchronous function that does calculations behind a draw loop without slowing it down. I have read many callback examples and am clearly doing something wrong.

I have created a simplified version of what I would like to do. When you click your mouse it should do the math without hanging up the draw loop. Right now it causes a hangup:

var nPoints = 1;
var sumDone = false;
var sum = 0;

function setup() {
    var myCanvas = createCanvas(200, 200);
    myCanvas.parent("p5");
}

function draw(){
  nPoints = nPoints+1
  stroke(0,0,0);
  background(245,245,245);
  noFill();
  rect(1,1,198,198);
  textAlign(CENTER);
  fill(0,0,0);
  textSize(20);
  if(sumDone){
    text(sum,100,20);
  }else{
    text("not done",100,20);
  }
  noStroke();
  push();
  translate(100,100);
  rotate(nPoints/50);

  rect(-50,-10,100,20);
  pop();
  
}

function mouseClicked(){
  if(sumDone){
    sumDone = false;
    sum=0;
  }else{
    doMath(function (){
      sumDone = true;
    });
  }
}

function doMath(callback){
    for(var i=0;i<10000000;i++){
      sum = sum + i;
    }
  callback();
}
<head>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.16/p5.js"></script>


<body>
  <div id="p5" align="center">
  </div>
  <script>
    <!-- JAVASCRIPT CODE GOES HERE -->
  </script>
</body>

As you can see, the math still completely hangs up the draw loop. Is it possible to do this in a way where the draw loop is not effected?

Murenrb
  • 367
  • 2
  • 12
  • If you want to run something asynchronously, the basic method is to use setTimeout (or setInterval) to separate it from the main thread. Unless a process is *extremely* taxing, you generally don't need to try to make it behave as if it's async, though. – CertainPerformance Mar 19 '18 at 23:30
  • But `setTimeout` just delays it a period of time, no? How would I use it in this case? – Murenrb Mar 20 '18 at 01:42
  • A function can recursively call setTimeout on itself. For example `const myFn = () => { console.log('run'); setTimeout(myFn, 1000); }; myFn();` This lets it run completely independently of the main thread. – CertainPerformance Mar 20 '18 at 01:52
  • Sorry @CP. I implemented that, but it still slows down the main drawthread just every 1000s. It runs independent, but still takes over the tread because it is a single thread. – Murenrb Mar 21 '18 at 14:56

1 Answers1

0

JavaScript is single-threaded. Moving the work to a callback function just ties up the thread that's used to run draw() and every other JavaScript function.

The only way to offload work like this is to do it on the server and use AJAX to query for the result.

Other than that, perhaps try breaking the calculation down into smaller chunks. Can you do 10% of the calculation per frame or something?

Edit: These threads mention the concept of web workers which you might look into.

Kevin Workman
  • 41,537
  • 9
  • 68
  • 107