终止无响应/无限循环的WebWorker(Javascript)

kiayqfof  于 2023-06-20  发布在  Java
关注(0)|答案(4)|浏览(261)

我正在编写一种用于教育目的的语言,它应该在Web浏览器中运行。该语言编译为JavaScript。
因此,存在无限循环和递归的问题。在那之前,我一直认为解决方案是将运行时实现为WebWorker和UI上的一个按钮,以便在运行时间过长时终止它。
我刚刚发现,在测试我的语言时,web worker并没有真正被终止,通过调用:runtime.terminate() ;
至少在他最后一份工作完成之前,我还没有测试过如果它完成了会发生什么。即使在我到目前为止找到的文档中,它也声明它会立即停止执行。
因此,即使用户可以继续以这种方式工作,在后台运行的worker也会耗尽资源,导致至少一个浏览器没有响应。
因此,我需要在无限循环或递归的情况下终止执行的任何方法,以响应用户事件。由于我没有找到任何方法在JavaScript中将线程置于睡眠状态,因此这也不起作用,或者是否有类似于Web工作者的睡眠的东西?
你对我能做什么有什么建议吗?

7vux5j2d

7vux5j2d1#

我会这样做:
1)让你的编译器生成代码,而不是从头到尾执行程序,它把它分成段-例如,循环的主体或函数的主体可以是一个段。
2)每个段都应该以timeoutId = setTimeout(nextSegment, 0)结束。这允许web worker在执行段之间接收和响应异步事件。
3)当你想终止Web Worker时,使用window.postMessage()向它发送一个异步消息。
4)在Web Worker内部,有一个事件处理程序,在接收到该消息时,它会执行clearTimeout(timeoutId)

g0czyy6m

g0czyy6m2#

我最近对此很好奇,我刚刚测试了一下。在Chrome和Firefox(截至2023年)中,无限循环 * 被 * worker.terminate()中断。
然而,在Chrome中,终止需要几秒钟的时间,而在Firefox中,它会立即发生。我发布了一个关于这个here的crbug问题。
您可以通过运行以下代码在您选择的浏览器中测试该行为:

let myWorker = new Worker(URL.createObjectURL(new Blob([`
  self.onmessage = function() {
    let i = 1;
    while(i++){
      if(i % 10000000 === 0) console.log(i);
    }
  }
`], { type: 'text/javascript' })));

myWorker.postMessage('start');

setTimeout(() => {
  console.log('Terminating worker...');
  myWorker.terminate();
}, 5000);

在Chrome中,console.log(i)会在Terminating worker...记录后几秒钟出现,而在Firefox中,Terminating worker...总是最后记录的内容。

pkln4tw6

pkln4tw63#

谢谢你的回应,我已经考虑过这种方式,所以实际上我不需要网络工作者。因此,这种方法的缺点是:
1)我必须把循环实现为递归函数调用...
更大的问题是2)段的大小必须限制在一个命令上,这种方法实际上是有效的,所以我必须将每个命令 Package 到一个函数中,该函数调用下一个命令,这将是一个巨大的开销......
这就是为什么我正在寻找一条路,如果有任何?

ve7v8dk2

ve7v8dk24#

是的,我正在写一个编译器。
在使用这种方法时,我必须提到,用户的开销可能不多,但对编译的影响确实很大……这就像在Javascript之上构建一个VM...
我得到的这一点是,除了上述几点,我还需要:

  • 需要一个复杂的索引系统来进行函数命名-照顾变量分配-必须串行求解表达式-...
    这就是为什么我正在寻找一个更优雅的变种...

相关问题