如何存储来自 ScriptManager 的函数句柄供以后使用?
How to store function handles from ScriptManager for later usage?
tl;博士:
do/can 我如何将多个 js 函数的函数句柄存储在 java 中以供以后使用?目前我有两个想法:
创建多个 ScriptEngine 实例,每个实例包含一个加载函数。按列将它们存储在地图中,列表中每列有多个条目。看起来开销很大,具体取决于 'heavy' ScriptEngine 实例是如何...
一些 Javascript 解决方案将同一目标字段的方法附加到数组。还不知道如何从 java 端访问它,但也不喜欢它。想让脚本文件尽可能愚蠢。
var test1 = test1 || [];
test1.push(function(input) { return ""; });
???
想法或建议?
告诉我更多:
我有一个项目,其中有一个包含脚本文件的目录(javascript,预计将来会增加一百多个文件)。这些脚本文件的命名方式如下:test1;toupper.js
、test1;trim.js
和 test2;capitalize.js
。分号之前的名称是脚本将处理的 column/field ,分号之后的部分是人类可读的描述文件的作用(简化示例)。因此,在此示例中,有两个脚本将分配给“test1”列,一个脚本将分配给“test2”列。 js-function 模板基本上是这样的:
function process(input) { return ""; };
我的想法是,在服务器启动时加载(和evaluate/compile)所有脚本文件,然后在需要时按列使用加载的函数。到目前为止,还不错。
我可以 load/evaluate 使用以下代码的单个函数。示例使用 GraalVM,但也应该可以用其他语言重现。
final ScriptEngine engine = new ScriptEngineManager().getEngineByName("graal.js");
final Invocable invocable = (Invocable) engine;
engine.eval("function process(arg) { return arg.toUpperCase(); };");
var rr0 = invocable.invokeFunction("process", "abc123xyz"); // rr0 = ABC123XYZ
但是当我 load/evaluate 下一个具有相同名称的函数时,前一个函数将被覆盖 - 从逻辑上讲,因为它具有相同的函数名称。
engine.eval("function process(arg) { return arg + 'test'; };");
var rr1 = invocable.invokeFunction("process", "abc123xyz"); // rr1 = abc123xyztest
我就是这样做的。
使用 Graal.js 的推荐方法是通过多语言 API:https://www.graalvm.org/reference-manual/embed-languages/
使用 ScriptEngine API 可能不一样,但这里是使用多语言 API.
的示例
- 将函数定义包装在
()
中
- return Java
的函数
- 图中未显示,但您可能构建了一个从列名称到要在其上调用的函数列表的映射。
- 对数据调用函数。
import org.graalvm.polyglot.*;
import org.graalvm.polyglot.proxy.*;
public class HelloPolyglot {
public static void main(String[] args) {
System.out.println("Hello Java!");
try (Context context = Context.create()) {
Value toUpperCase = context.eval("js", "(function process(arg) { return arg.toUpperCase(); })");
Value concatTest = context.eval("js", "(function process(arg) { return arg + 'test'; })");
String text = "HelloWorld";
text = toUpperCase.execute(text).asString();
text = concatTest.execute(text).asString();
System.out.println(text);
}
}
}
现在,Value.execute()
return 是一个 Value
,为了简单起见,我用 asString()
强制转换为 Java 字符串,但你没有为此,您可以对 Value
进行操作(这里是 API 的值:https://www.graalvm.org/sdk/javadoc/org/graalvm/polyglot/Value.html)。
tl;博士:
do/can 我如何将多个 js 函数的函数句柄存储在 java 中以供以后使用?目前我有两个想法:
创建多个 ScriptEngine 实例,每个实例包含一个加载函数。按列将它们存储在地图中,列表中每列有多个条目。看起来开销很大,具体取决于 'heavy' ScriptEngine 实例是如何...
一些 Javascript 解决方案将同一目标字段的方法附加到数组。还不知道如何从 java 端访问它,但也不喜欢它。想让脚本文件尽可能愚蠢。
var test1 = test1 || []; test1.push(function(input) { return ""; });
???
想法或建议?
告诉我更多:
我有一个项目,其中有一个包含脚本文件的目录(javascript,预计将来会增加一百多个文件)。这些脚本文件的命名方式如下:test1;toupper.js
、test1;trim.js
和 test2;capitalize.js
。分号之前的名称是脚本将处理的 column/field ,分号之后的部分是人类可读的描述文件的作用(简化示例)。因此,在此示例中,有两个脚本将分配给“test1”列,一个脚本将分配给“test2”列。 js-function 模板基本上是这样的:
function process(input) { return ""; };
我的想法是,在服务器启动时加载(和evaluate/compile)所有脚本文件,然后在需要时按列使用加载的函数。到目前为止,还不错。
我可以 load/evaluate 使用以下代码的单个函数。示例使用 GraalVM,但也应该可以用其他语言重现。
final ScriptEngine engine = new ScriptEngineManager().getEngineByName("graal.js");
final Invocable invocable = (Invocable) engine;
engine.eval("function process(arg) { return arg.toUpperCase(); };");
var rr0 = invocable.invokeFunction("process", "abc123xyz"); // rr0 = ABC123XYZ
但是当我 load/evaluate 下一个具有相同名称的函数时,前一个函数将被覆盖 - 从逻辑上讲,因为它具有相同的函数名称。
engine.eval("function process(arg) { return arg + 'test'; };");
var rr1 = invocable.invokeFunction("process", "abc123xyz"); // rr1 = abc123xyztest
我就是这样做的。
使用 Graal.js 的推荐方法是通过多语言 API:https://www.graalvm.org/reference-manual/embed-languages/
使用 ScriptEngine API 可能不一样,但这里是使用多语言 API.
的示例- 将函数定义包装在
()
中
- return Java 的函数
- 图中未显示,但您可能构建了一个从列名称到要在其上调用的函数列表的映射。
- 对数据调用函数。
import org.graalvm.polyglot.*;
import org.graalvm.polyglot.proxy.*;
public class HelloPolyglot {
public static void main(String[] args) {
System.out.println("Hello Java!");
try (Context context = Context.create()) {
Value toUpperCase = context.eval("js", "(function process(arg) { return arg.toUpperCase(); })");
Value concatTest = context.eval("js", "(function process(arg) { return arg + 'test'; })");
String text = "HelloWorld";
text = toUpperCase.execute(text).asString();
text = concatTest.execute(text).asString();
System.out.println(text);
}
}
}
现在,Value.execute()
return 是一个 Value
,为了简单起见,我用 asString()
强制转换为 Java 字符串,但你没有为此,您可以对 Value
进行操作(这里是 API 的值:https://www.graalvm.org/sdk/javadoc/org/graalvm/polyglot/Value.html)。