Как зациклить веб-работника? - PullRequest
0 голосов
/ 02 мая 2018

Я создаю веб-сайт, на котором с помощью 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: превышен максимальный размер стека вызовов

Как мне решить эту проблему, я бы хотел, чтобы рабочий работал для каждого (или пока пользователь не закроет страницу)

EDIT: Чтобы было ясно, код, который я разместил выше, работает! но он перестает работать, когда я заменяю setTimeout("calculate()", 1); на calculate();

Ответы [ 2 ]

0 голосов
/ 02 мая 2018

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);
0 голосов
/ 02 мая 2018

Преимущество рабочих заключается в том, что они позволяют перенести тяжелую обработку из основного потока. Если вы удалите setTimeout из своего кода, вы все равно будете отправлять большую часть обработки в основной поток, уже не для вычисления PI, а для обработки рабочих сообщений.

Итак, идея состоит в том, чтобы обработать как можно дольше, прежде чем отправлять сообщение в основной поток. Например, в вашем приложении вы можете выполнить много итераций и отправить результат в одном сообщении:

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