javascript - 试图在生成器中使用 setTimeout 来控制生成随机数的过程但失败了

标签 javascript ecmascript-6

我试图实现一个种子伪随机生成器。它会产生随机数,直到时间到了。代码如下

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。我猜循环没有停止。到底出了什么问题?

最佳答案

脚本中的所有同步代码都将在回调有机会运行之前执行。如果您有阻塞的代码(例如在 while 循环中不停地yield),回调将永远没有机会运行.

出于类似的原因,下面的代码永远不会退出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 毫秒内生成的元素数量可能有很大的范围,具体取决于处理器/浏览器在那段时间还做了什么。

感谢 Kaiido,为避免阻塞可见的 UI,您可以考虑将脚本的阻塞部分移至 worker:

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

关于javascript - 试图在生成器中使用 setTimeout 来控制生成随机数的过程但失败了,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56387725/

相关文章:

javascript - 如何防止在 ClickFunnels 上提交表单

javascript - 防止触发多个点击事件 : ReactJS

javascript - 为什么在调用 foo.fn() 时 JS 不总是将 `this` 绑定(bind)到 `foo`?

javascript - 在 ReactJS 中将 json 结果推送到数组的正确方法是什么?

javascript - 如何中和注入(inject)的远程 Ajax 内容?

javascript - 我应该如何确定苹果可以放置在特定位置?

javascript - 在图表中显示 json 数据

javascript - 全局符号注册表是否可以直接访问?

node.js - 语法错误 : Unexpected token 'const' -- despite the fact that I replaced const

Javascript:简单的加法程序不起作用