简体   繁体   中英

How to loop a Web Worker?

I'm making a website where using PHP, AJAX and Javascript the user can help to calculate PI, this is purely for learning purposes and I'm know there are more efficient ways to calculate PI.

I need to pick a random location and then look if it's in a circle, there for I have created this code

var size = 500;

function calculate() {
    var Xpos = Math.floor(Math.random() * size);
    var Ypos = Math.floor(Math.random() * size);

    var dist = Math.hypot(Ypos-Xpos, size / 2 - size / 2);

    if (dist <= size / 2) postMessage(true);
    else postMessage(false);

    setTimeout("calculate()", 1);
}

calculate();

Which works great, altough it could be faster since there's a unneeded timeout in there (I think its uneeded anyway), so If I just remove it and replace it with only calculate(); to speed it up I get this error

Uncaught RangeError: Maximum call stack size exceeded

How do I solve this, I would like to keep the worker working for every (or until the user closes the page)

EDIT: To be clear, the code I posted above works! but it stops working when I replace setTimeout("calculate()", 1); with calculate();

The advantage of workers is that they allow you to move the heavy processing from the main thread. If you remove the setTimeout from your code you will still be sending a lot of processing to the main thread, not anymore for calculating the PI, but still for processing the worker messages.

So, the idea is to process for as long as possible before sending a message to the main thread. For example, in your application you could run many iterations and send the result in one message:

const size = 500;

function calculate() {
    const iterations = 100000;
    while (true) { // you will probably want to have a condition to stop
      let inside = 0;
      for (let i = 0; i < iterations; i++) {
        var Xpos = Math.floor(Math.random() * size);
        var Ypos = Math.floor(Math.random() * size);

        var dist = Math.hypot(Ypos-Xpos, size / 2 - size / 2);

        if (dist <= size / 2) {
          inside++;
        }
      }
      postMessage({iterations, inside});
    }
}

calculate();

setTimeout([func],delay) waits the defined amount of delay then calls the function once and stops, so calling it over and over right away overflows the stack because there was no gap for the ressources to be released.

And

An infinite while loop will freeze the page

And Since you want to be running for as long as the page is alive you need to use setInterval which keeps calling the function every so often (your dely) until you close the page.

var size = 500;
setInterval(function() {
    var Xpos = Math.floor(Math.random() * size);
    var Ypos = Math.floor(Math.random() * size);

    var dist = Math.hypot(Ypos-Xpos, size / 2 - size / 2);

    if (dist <= size / 2) postMessage(true);
    else postMessage(false);

}, 1);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM