javascript - 我如何编写一个 Java 方法,从服务器端 JavaScript 调用,它将 JS 回调函数作为参数?

标签 javascript java rhino

我正在尝试编写一个 Java API,它将从在 JDK 7 JS 引擎下运行的服务器端 JavaScript 调用。这个想法是让消费者能够编写如下 JS 代码,注册一个回调,稍后由另一个调用 Java 方法执行:

myJavaObj.registerCallback(function (param) {
  // do stuff here
});
myJavaObj.methodThatTriggersCallback();

这是我正在使用的一些测试代码:

import javax.script.Invocable;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

public class JSTestClient {

    private String successCallback;

    public void handleSuccess(String successCallback) {
        this.successCallback = successCallback;
    }

    public void doStuff() throws ScriptException, NoSuchMethodException {
        ScriptEngineManager manager = new ScriptEngineManager();
        Invocable engine = (Invocable) manager.getEngineByName("JavaScript");
        engine.invokeFunction(successCallback, "TEST SUCCESS");
    }
}
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

public class Main {
    public static void main(String[] args) {
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("JavaScript");
        String js =
                "var client = new Packages.JSTestClient();\n" +
                "client.handleSuccess(function (response) {\n" +
                "  java.lang.System.out.println(response);\n" +
                "});\n" +
                "client.doStuff();";
        try {
            engine.eval(js); // Expecting this to output "TEST SUCCESS"
        } catch (ScriptException e) {
            e.printStackTrace();
        }
    }
}

但是当我运行它时,我得到一个 java.lang.NoSuchMethodException 因为它正在解释字符串:

function (response) {
    java.lang.System.out.println(response);
}
作为函数名。有没有办法创建这样的回调,或者我是否需要使用其他约定?

最佳答案

您的 handleSuccess 方法采用 String 作为参数,但您使用 JavaScript function 对象调用它。您需要更改它以接受 Function .

由于您使用的是 Java 7,因此您使用的是经过修改的 Mozilla Rhino引擎,实现类从包中移出 org.mozilla.javascriptsun.org.mozilla.javascript.internal

要让您的代码运行,请将 JSTestClient 替换为:

import sun.org.mozilla.javascript.internal.Context;
import sun.org.mozilla.javascript.internal.Function;

public class JSTestClient {

    private Function successCallback;

    public void handleSuccess(Function successCallback) {
        this.successCallback = successCallback;
    }

    public void doStuff() {
        this.successCallback.call(Context.getCurrentContext(), null, null,
                                  new Object[] { "TEST SUCCESS" });
    }
}

注意Java 8改用了Nashorn引擎,与Nashorn交互的代码完全不同。

关于javascript - 我如何编写一个 Java 方法,从服务器端 JavaScript 调用,它将 JS 回调函数作为参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48919126/

相关文章:

java - 在Android中调用asynctask时出现计时器错误

wcf - MSMQ:2台服务器是否需要在同一个域中才能访问私有(private)队列?

java - 我如何实际运行 Rhino?

javascript - Persistence.js 在两个方向上添加多对多

java - 更改 REST API 的 URL 模式

java - 如何在 Netbeans 平台 Maven 插件中找到图像路径

java - 在 Rhino Javascript 中共享 java 对象

javascript - 使用jquery过滤带有选择框选项值的json

javascript - JavaScript 中变量的大小

c# - 根据应用程序设置有选择地输出 javascript 的好方法