我只能看到有关nashorn中loadWithNewGlobal用法的简单参考。
我只是想知道如何使用loadWithNewGlobal在nashorn中执行JavaScirpt的大量内容。我的javascript内容将具有多个JS方法。
在简单的JavaScript内容下面,当使用loadWithNewGlobal时可以正常工作。
String script = new StringBuilder("var script = 'var i = 0;i += 1;i += 1;';")
.append("function addition() {")
.append("return loadWithNewGlobal({ name: \"addition\", script: script });")
// .append("return load({ name: \"addition\", script: script });")
.append("}").toString();
从上面的代码中,我了解到loadwithNewGlobal的
script
参数是一个js变量,最后的算术运算结果将能够通过使用callable方法来检索。我尝试通过在脚本中加载一个简单的方法来尝试,但是得到了意外的结果。
String script = new StringBuilder("var script= 'var a = function testFunction() { var i = 0;i += 1;i += 1; return i;}';")
.append("function addition() {")
.append("return loadWithNewGlobal({ name: \"addition\", script: script });")
// .append("return load({ name: \"addition\", script: script });")
.append("}").toString();
任何人都可以帮助我获得一些使用loadWithNewGlobal的很好的例子,以更好地理解或者关于如何使用loadWithNewGlobal执行大型js内容的任何想法?
更新更多详细信息:
我只想在并行线程Java环境(Java1.8)中执行大型Javascirpt内容。由于它是并行线程环境,请尝试使用loadWithNewGlobal以避免全局变量发生串扰。
下面的示例代码,我正在尝试并期望结果,如果所有10个线程中有5个。
但是获取类型转换异常,也由ScriptObjectMirror尝试,但无法获得预期的输出。
关于我在这里想念的任何想法吗?
import java.util.ArrayList;
import java.util.Date;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import jdk.nashorn.api.scripting.ScriptObjectMirror;
public class LoadWithNewGlobal {
private static Invocable invocableEngine;
private static ScriptEngine jsEngine;
public static String customFunction() {
String resultValue= null;
try{
ScriptEngineManager factory = new ScriptEngineManager();
jsEngine = factory.getEngineByName("nashorn");
StringBuffer scrFile = new StringBuffer();
String scriptContent = "var a=function() { var i=1; i+=2; i+=2; return i+'';}; a;";
scrFile.append("function testFunction() {");
scrFile.append("var obj = loadWithNewGlobal({name:\"foo\", script : \""+scriptContent+"\" });");
scrFile.append("return obj;}");
System.out.println(scrFile.toString());
jsEngine.eval(scrFile.toString());
invocableEngine = (Invocable) jsEngine;
Callable<String> newEncrypt = new Callable<String>() {
public String call() {
String val = null;
try {
val = (String) invocableEngine.invokeFunction("testFunction");
// ScriptObjectMirror sobj = (ScriptObjectMirror) invocableEngine.invokeFunction("testFunction");
// System.out.println("The foo Value is :"+sobj.get("foo"));
} catch (Exception e) {
throw new RuntimeException(e);
}
return val;
}
};
ExecutorService executor = Executors.newCachedThreadPool();
ArrayList<Future<String>> results = new ArrayList<Future<String>>();
for(int i=0; i< 10; i++){
//submit Callable tasks to be executed by thread pool
//add Future to the list, we can get return value using Future
results.add(executor.submit(newEncrypt));
}
for(Future<String> fut : results){
System.out.println(new Date()+ "::"+fut.get().toString());
}
executor.shutdown();
}catch(Exception e){
e.printStackTrace();
}
return resultValue;
}
public static void main(String[] args) {
System.out.println("Result :"+customFunction());
}
}
最佳答案
这个问题对我来说不是很清楚。请注意,您正在使用函数值定义变量,因此整个脚本的计算结果为“未定义”(因为这是变量声明语句)
在以下修改中,我在var decl之后添加了“ a”。声明:
var obj = loadWithNewGlobal({
name: "foo",
script: "var a = function() { print('hello') }; a"
});
print(obj);
obj()
进行此更改后,函数对象将作为loadWithNewGlobal调用的值返回-可以调用它。
黑白之间的唯一区别是“ load”和“ loadWithNewGlobal”:后者创建一个新的ECMAScript全局作用域对象并评估其中的脚本,因此返回的值都是脚本对象“ mirrors”-但是将镜像像普通对象一样透明地对待越多越好。