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 .为此(以简化的方式):
- Java:: 创建一个 DummyLogger class
.
public class DummyLogger {
void log(String msg) {
System.out.println("LOG (JS) : " + msg);
}
}
- 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);
- 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 的重点...)。
我的想法是做这样的事情:
- 在JS logger模块上添加一个函数setJavaLogger(记录器)
- 使用 setter 将 javaLogger 直接注入记录器模块
.
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...
您将不得不找到一种或多或少有创意的方式来等待您的模块加载。
在试验 JavaFX + HTML5/JS 时,我遇到了 AMD 模块 (RequireJS)。
我知道如何注入 Java 对象并在“老式”Java脚本(全局范围内的所有内容)中使用它们,但我现在想知道如何注入RequireJS 模块中的一个 Java 对象。
有什么建议吗?
更新 1
感觉自己说的不够清楚,再具体一点吧。
我的目标是在浏览器控制台和 Java 控制台上显示我的 Java 脚本日志,因为我不想包含 firebug-lite.j .为此(以简化的方式):
- Java:: 创建一个 DummyLogger class
.
public class DummyLogger {
void log(String msg) {
System.out.println("LOG (JS) : " + msg);
}
}
- 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);
- 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 的重点...)。
我的想法是做这样的事情:
- 在JS logger模块上添加一个函数setJavaLogger(记录器)
- 使用 setter 将 javaLogger 直接注入记录器模块
.
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...
您将不得不找到一种或多或少有创意的方式来等待您的模块加载。