我正在编写一种用于教育目的的语言,它应该在Web浏览器中运行。该语言编译为JavaScript。
因此,存在无限循环和递归的问题。在那之前,我一直认为解决方案是将运行时实现为WebWorker和UI上的一个按钮,以便在运行时间过长时终止它。
我刚刚发现,在测试我的语言时,web worker并没有真正被终止,通过调用:runtime.terminate()
;
至少在他最后一份工作完成之前,我还没有测试过如果它完成了会发生什么。即使在我到目前为止找到的文档中,它也声明它会立即停止执行。
因此,即使用户可以继续以这种方式工作,在后台运行的worker也会耗尽资源,导致至少一个浏览器没有响应。
因此,我需要在无限循环或递归的情况下终止执行的任何方法,以响应用户事件。由于我没有找到任何方法在JavaScript中将线程置于睡眠状态,因此这也不起作用,或者是否有类似于Web工作者的睡眠的东西?
你对我能做什么有什么建议吗?
4条答案
按热度按时间7vux5j2d1#
我会这样做:
1)让你的编译器生成代码,而不是从头到尾执行程序,它把它分成段-例如,循环的主体或函数的主体可以是一个段。
2)每个段都应该以
timeoutId = setTimeout(nextSegment, 0)
结束。这允许web worker在执行段之间接收和响应异步事件。3)当你想终止Web Worker时,使用
window.postMessage()
向它发送一个异步消息。4)在Web Worker内部,有一个事件处理程序,在接收到该消息时,它会执行
clearTimeout(timeoutId)
。g0czyy6m2#
我最近对此很好奇,我刚刚测试了一下。在Chrome和Firefox(截至2023年)中,无限循环 * 被 *
worker.terminate()
中断。然而,在Chrome中,终止需要几秒钟的时间,而在Firefox中,它会立即发生。我发布了一个关于这个here的crbug问题。
您可以通过运行以下代码在您选择的浏览器中测试该行为:
在Chrome中,
console.log(i)
会在Terminating worker...
记录后几秒钟出现,而在Firefox中,Terminating worker...
总是最后记录的内容。pkln4tw63#
谢谢你的回应,我已经考虑过这种方式,所以实际上我不需要网络工作者。因此,这种方法的缺点是:
1)我必须把循环实现为递归函数调用...
更大的问题是2)段的大小必须限制在一个命令上,这种方法实际上是有效的,所以我必须将每个命令 Package 到一个函数中,该函数调用下一个命令,这将是一个巨大的开销......
这就是为什么我正在寻找一条路,如果有任何?
ve7v8dk24#
是的,我正在写一个编译器。
在使用这种方法时,我必须提到,用户的开销可能不多,但对编译的影响确实很大……这就像在Javascript之上构建一个VM...
我得到的这一点是,除了上述几点,我还需要:
这就是为什么我正在寻找一个更优雅的变种...