用Rhino在Java中解释JavaScript:暂停/恢复脚本
Interpreting JavaScript in Java with Rhino: pausing/resuming scripts
我正在使用javax.script。JDK的*包。具体来说,我使用的是JavaScript引擎,据我所知,它似乎是基于mozilla开发的JavaScript-in- java解释器Rhino。
我希望完成的是基本上让我的JavaScript能够在代码中的某个点(例如,在函数调用的中途)"暂停"自己,并且只有在Java允许的情况下才恢复自己。
为了说明我的意思,想象一下这个JavaScript代码:
function myJSFunction() {
print("Hello ");
mysteriousPauseFunction(); // this is the part I'm wondering about. basically, the script should break here and resume later at Java's discretion...
// upon reaching this comment, we know now that Java has told JavaScript that it's okay to resume, so the next line will now be executed...
print("world");
}
如果"暂停"/"中断"部分涉及绑定Java函数并将其传递给当前scriptenengine的引用或其他内容,那对我来说很酷。我想这可能会涉及到:从Java中暂停JavaScript。
我在谷歌上搜索了一下,发现这里的关键字似乎是"延续"。据我所知,Rhino只支持解释模式下的延续(相对于编译模式),我认为这可以通过将"context"设置为-2来实现。由于内置的JDK ScriptEngine似乎没有提到任何关于上下文的内容(或者可能我遗漏了它),这是否意味着我必须下载并直接使用Mozilla的Rhino库?
我需要Rhino的延续来完成这个吗?我找到了一个关于Rhino延续的有用教程,但是在通读之后,我不能100%确定它是否能够完成我上面描述的内容。如果这个是我正在寻找的,那么我的后续问题是关于提到的"序列化":这是否意味着当我恢复脚本时,除非我序列化它们,否则所有变量都将被取消设置?
Update:看起来这在Rhino中是可能的。这是目前为止我的JavaScript;在代码之后,我将解释它的作用…
var end = new Continuation();
function myJSFunction()
{
print("Hello ");
var kont = new Continuation();
storePause(script, kont); // script is previously bound by Java into the JavaScript. it is a reference to the script itself.
end();
print("world");
}
我的"storePause()"函数是我写的一个Java函数,它被绑定到JavaScript,但现在,它不做任何事情。我的下一个目标是充实它的代码,这样它就可以将延续和脚本信息存储为Java对象,以便Java以后可以恢复脚本。
现在,它所做的是在打印"Hello"之后,但在打印"world"之前暂停/"中断"脚本,所以这向我证明了用这种方式暂停脚本是可能的。
所以,我现在要弄清楚的是如何恢复延续。请注意,上面的工作在默认情况下使用JDK脚本引擎(此时我不需要担心解释模式和编译模式——它似乎默认为解释模式),但看起来恢复脚本的过程将需要Mozilla的Rhino库。
好吧,我花了很多时间挖掘文档、教程和示例,并在这里和Rhino Google Group上发帖,但我已经设法编译了一个工作解决方案。由于似乎没有完整的例子,我将把我的发现张贴在这里,以便将来有人偶然发现这一点。
实际上,我的发现可能太长了,不能在这里发布,所以我决定在我的博客上写一个教程:
教程:Mozilla Rhino(用于Java的JavaScript解释器)中的continuation
希望这能帮助到别人。据我所知,这是唯一一个完整的Rhino教程,它展示了如何做以下所有事情:初始化Rhino,从JavaScript (*.js)文件加载脚本,自动绑定特定Java类(例如ScriptFunctions)中的所有函数作为JavaScript中的全局函数,最后调用JavaScript函数并处理该调用的延续。
基本上,问题是我需要首先下载Mozilla Rhino源代码(因为与JDK一起打包的版本已经过时,不支持延续),重写我所有的代码以使用官方Rhino包的语法(它与JDK的ScriptingEngine语法非常不同),编写一个Java函数,抛出ContinuationPending异常并将其绑定到JavaScript,以便JavaScript可以调用它(因为直接从JavaScript抛出ContinuationPending会导致抛出JavaScriptException,而不是抛出ContinuationPending,甚至试图调用getCause()在JavaScriptException上导致null),然后在我的Java代码中调用我的JavaScript函数("myJSFunction"在我最初的示例中),使用try/catch块来检查ContinuationPending(这是一个异常),然后使用该ContinuationPending稍后恢复脚本。
唷。这很艰难,但现在一切都值得了。
您没有解释为什么要这样做,但是我正在模拟一个与最终用户交互的程序,像这样:
print('Hello!');
a=Number(input('enter a number'));
b=Number(input('and another number'));
print('the sum of '+a+' plus '+b+' is '+(a+b))
我已经得到了它的工作只是通过创建一个打印和输入函数在javascript检查程序状态。
你可以在这里看到一个演示。
它都是用javascript写的,所以你可以在任何浏览器上查看源代码。
希望有帮助
你可以使用wait/notify:
public final class Pause {
private final Object lock = new Object();
public void await() throws InterruptedException {
synchronized (lock) {
lock.wait();
}
}
public void resumeAll() {
synchronized (lock) {
lock.notifyAll();
}
}
}
用法:
final Pause pause = new Pause();
class Resumer implements Runnable {
@Override public void run() {
try {
Thread.sleep(5000);
pause.resumeAll();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
new Thread(new Resumer()).start();
SimpleBindings bindings = new SimpleBindings();
bindings.put("pause", pause);
String script = "print('Hello, ');'n"
+ "pause.await();'n"
+ "println('ECMAScript!');'n";
new ScriptEngineManager().getEngineByName("ECMAScript")
.eval(script, bindings);
这是一个相对简单的解决方案,因为你没有提到任何其他约束。wait()
导致线程阻塞,这在所有环境中都是不可接受的。如果您想并发运行脚本,也没有简单的方法来识别哪些线程正在等待Pause
实例。
注意:await()
上的InterruptedException
应该由调用者处理,或者在await()
中做一些更明智的事情。
- 如何临时暂停浏览器渲染,然后恢复整个页面
- NodeJS-readline暂停和恢复事件发射器(逐行读取)
- 如何暂停和恢复jquery间隔
- 我如何暂停和恢复这个动画,它可以用纯CSS完成吗
- 当用户将鼠标移到屏幕/图表上时,自动滚动将暂停.如果鼠标移动停止,自动滚动将再次恢复
- 暂停和恢复setTimeouts数组
- Web Audio API从暂停状态恢复
- WebRTC 暂停和恢复流
- 需要能够暂停和恢复设置超时
- 蒸发.js暂停/恢复
- 电话间隙媒体 API 暂停/恢复
- NodeJS流暂停/恢复不适用于XMLHttpRequest,但适用于curl
- PhantomJS-暂停/恢复javascript执行
- 用Rhino在Java中解释JavaScript:暂停/恢复脚本
- 如何完全停止jQuery循环函数的运行(不是暂停/恢复)
- JWPlayer -禁用点击视频暂停/恢复
- 是否可以从JS暂停/恢复/操作一个swift对象?
- javascript倒计时定时器暂停恢复
- Howler js暂停/恢复故障
- jQuery暂停/恢复动画