JavaFX + Javascript : 如何将 Java 对象注入 AMD 模块

JavaFX + Javascript : How to inject a Java object to an AMD module

在试验 JavaFX + HTML5/JS 时,我遇到了 AMD 模块 (RequireJS)。

我知道如何注入 Java 对象并在“老式”Java脚本(全局范围内的所有内容)中使用它们,但我现在想知道如何注入RequireJS 模块中的一个 Java 对象。

有什么建议吗?


更新 1

感觉自己说的不够清楚,再具体一点吧。

我的目标是在浏览器控制台和 Java 控制台上显示我的 Java 脚本日志,因为我不想包含 firebug-lite.j .为此(以简化的方式):

  1. Java:: 创建一个 DummyLogger class

.

public class DummyLogger {
    void log(String msg) {
       System.out.println("LOG (JS) : " + msg); 
    }
}
  1. Java:: 将 DummyLogger 实例添加到 Java 脚本 window 对象

.

WebView webView = new WebView()
webView.getEngine().load("index.html");
// Inject our Java logger interface to JS
final JSObject jsWnd = (JSObject) webView.getEngine().executeScript("window");
jsWnd.setMember("javaLogger", logger);
  1. Javascript:: 在我的模块“module/logger.js”中,公开一个日志函数,如果定义了它,它会同时使用 JS 控制台和 javaLogger

.

define(function() {
    return {
        log: function(message) {
            console.log(message);

            // Forward to the injected Java logger only if it is defined
            if(typeof javaLogger !== 'undefined') {
                javaLogger.log(message);
            }
        }
    }
}

现在,我想知道是否可以在不污染 window 命名空间的情况下将 javaLogger 对象注入记录器模块(这是 AMD 的重点...)。

我的想法是做这样的事情:

.

WebView webView = new WebView()
WebEngine engine = webView.getEngine();

engine.getLoadWorker().stateProperty().addListener(
    (observable, oldState, newState) -> {
        if (newState == Worker.State.SUCCEEDED) {
            final JSObject retVal = (JSObject) engine.executeScript(
                "require(['module/logger'], function(logger) { return logger; });"
            );
            retVal.call("setJavaLogger", logger);
        }
    }
);

engine.load("index.html");

不幸的是,这没有任何作用。 require 函数 return 有什么用吗?

甚至可以在 Java 中检索我的记录器模块吗?

从 Java 开始,可以使用以下内容访问 RequireJS 模块:

WebView webView = new WebView();
WebEngine engine = webView.getEngine();
engine.load("path/to/index.html");

// Assuming that somewhere in 'index.html', the loading of "module/logger" is triggered...

{ ... let some time pass ...} // 

final JSObject loggerModule = (JSObject) engine.executeScript(
    "require('module/logger')"
);
logger.call("trace", "hello world!");

警告: HTML 页面和 RequireJS 模块的加载是异步的!

require(String) 的执行可能会失败并抛出 netscape.javascript.JSException,因为 'module/logger' 尚未加载。这种异常应如下所示:

netscape.javascript.JSException: Error: Module name "module/logger" has not been loaded yet for context: _. Use require([])
http://requirejs.org/docs/errors.html#notloaded
    at com.sun.webkit.dom.JSObject.fwkMakeException(JSObject.java:128)
    at com.sun.webkit.WebPage.twkExecuteScript(Native Method)
    at com.sun.webkit.WebPage.executeScript(WebPage.java:1426)
    at javafx.scene.web.WebEngine.executeScript(WebEngine.java:948)
    many more...

您将不得不找到一种或多或少有创意的方式来等待您的模块加载。