Попытка использовать setTimeout внутри генератора для управления процессом создания случайных чисел, но не удалось - PullRequest
3 голосов
/ 31 мая 2019

Я пытался реализовать сеяный псевдослучайный генератор. Он будет производить случайные числа, пока время не истекло. Код ниже

function* pseudoRandom(seed) {
  let random = seed;
  let flag = true;
  setTimeout(() => {flag = !flag}, 100); // stop generating after 100ms
  while (flag) {
    random = random * 16807 % 2147483647;
    yield random;
  }
}

let generator = pseudoRandom(1);

console.log([...generator]);

Но я все еще получаю сообщение об ошибке FATAL ERROR: invalid array length Allocation failed - JavaScript heap out of memory. Я думаю, что цикл не остановился. Так что же пошло не так?

1 Ответ

4 голосов
/ 31 мая 2019

Весь синхронный код в скрипте будет выполнен до того, как обратные вызовы получат возможность запуска. Если у вас есть код, который блокирует (например, бесконечно yield в цикле while без остановки), обратный вызов никогда не будет иметь возможности для запуска.

По тем же причинам следующий код никогда не выйдет из цикла while:

let flag = false;
setTimeout(() => flag = true);
while (!flag) {
  // do something
}

Проверьте, не прошло ли 100 мсек внутри вместо цикла:

function* pseudoRandom(seed) {
  let random = seed;
  const start = Date.now();
  while (Date.now() - start < 100) { // stop generating after 100ms
    random = random * 16807 % 2147483647;
    yield random;
  }
}

let generator = pseudoRandom(1);

console.log([...generator].length);

Обратите внимание, что число элементов, генерируемых за 100 мс, может иметь очень большой диапазон, в зависимости от того, что еще процессор / браузер делает в это время.

Спасибо, Кайидо. Чтобы не блокировать видимый пользовательский интерфейс, вы можете рассмотреть вопрос о переносе блокирующей части скрипта на рабочего:

// https://stackoverflow.com/questions/10343913/how-to-create-a-web-worker-from-a-string
// I put in a Stack Snippet for live demonstration
// in a real project, put this in a separate file
const workerFn = () => {
  function* pseudoRandom(seed) {
    let random = seed;
    const start = Date.now();
    while (Date.now() - start < 100) { // stop generating after 100ms
      random = random * 16807 % 2147483647;
      yield random;
    }
  }
  self.onmessage = ({ data }) => {
    let generator = pseudoRandom(1);
    const arr = [...generator];
    self.postMessage(arr.length);
  };
};
const workerFnStr = `(${workerFn})();`;
const blob = new Blob([workerFnStr], { type: 'text/javascript' });
const worker = new Worker(window.URL.createObjectURL(blob));

worker.onmessage = ({ data: length }) => console.log(length);
worker.postMessage(1234);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...