开发者问题收集

如何循环执行 Web Worker?

2018-05-02
3314

我正在制作一个网站,用户可以使用 PHP、AJAX 和 Javascript 来帮助计算 PI,这纯粹是为了学习目的,我知道有更有效的方法来计算 PI。

我需要选择一个随机位置,然后查看它是否在一个圆圈内,为此我创建了此代码

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();

效果很好,尽管它可能会更快,因为其中有一个不必要的超时(我认为它反正不需要),所以如果我只是删除它并用 calculate(); 替换它以加快速度,我会收到此错误

Uncaught RangeError: Maximum call stack size exceeded

我该如何解决这个问题,我想让工作人员一直工作(或者直到用户关闭页面)

编辑:明确地说,我上面发布的代码有效!但是当我用 calculate();

替换 setTimeout("calculate()", 1); 时它停止工作
2个回答

worker 的优点是它们允许您将繁重的处理从主线程移出。如果您从代码中删除 setTimeout ,您仍会将大量处理发送到主线程,不再用于计算 PI,但仍用于处理 worker 消息。

因此,这个想法是在将消息发送到主线程之前尽可能长时间地进行处理。例如,在您的应用程序中,您可以运行许多迭代并在一条消息中发送结果:

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();
Thiago Barcala
2018-05-02

setTimeout([func],delay) 等待定义的延迟量,然后调用一次函数并停止,因此一遍又一遍地调用它会立即溢出堆栈,因为没有释放资源的间隙。

并且

无限 while 循环将冻结页面

并且由于您希望在页面处于活动状态时一直运行,因此您需要使用 setInterval ,它会每隔一段时间(您的延迟)不断调用该函数,直到您关闭页面。

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);
2018-05-02