我使用了这段代码
public WebMap() {
webView = new WebView();
final WebEngine webEngine = webView.getEngine();
String url = getClass().getResource("map.html").toExternalForm();
webEngine.load(url);
final Deferred d = new Deferred();
webEngine.getLoadWorker().stateProperty().addListener(
new ChangeListener<State>() {
@Override
public void changed(ObservableValue ov, State oldState, State newState) {
if (newState == State.SUCCEEDED) {
d.resolve(webEngine);
}
}
}
);
readyWebEngine = d.promise();
}
我没有直接调用webEngine.executeScript,但我使用
readyWebEngine.then(new PromiseFunc() {
@Override
public Promise apply(Object oWebEngine) {
WebEngine webEngine = (WebEngine)oWebEngine;
webEngine.executeScript(script); // <=============================
// return value doesn't matter
return (new Deferred()).promise();
}
});
这样,script
字符串不会被评估,直到通过调用d.resolve()
来解决(履行)承诺
我们假设promise库是正确的
该代码对我来说效果很好,但是我的一位同事得到了这个令人沮丧的错误
netscape.javascript.JSException: ReferenceError: Can't find variable: gotoLatLng
[com.sun.webpane.platform.WebPage.twkExecuteScript(Native Method), com.sun.webpane.platform.WebPage.executeScript(WebPage.java:1438), javafx.scene.web.WebEngine.executeScript(WebEngine.java:811), packagename.WebMap.WebMap$1.apply(WebMap.java:36), packagename.WebMap.promise.Deferred$1$1.apply(Deferred.java:23), packagename.WebMap.promise.Deferred.resolve(Deferred.java:40), packagename.WebMap.WebMap$2.changed(WebMap.java:57), packagename.WebMap.WebMap$2.changed(WebMap.java:52), com.sun.javafx.binding.ExpressionHelper$SingleChange.fireValueChangedEvent(ExpressionHelper.java:196), com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:100), javafx.beans.property.ReadOnlyObjectWrapper$ReadOnlyPropertyImpl.fireValueChangedEvent(ReadOnlyObjectWrapper.java:195), javafx.beans.property.ReadOnlyObjectWrapper.fireValueChangedEvent(ReadOnlyObjectWrapper.java:161), javafx.beans.property.ObjectPropertyBase.markInvalid(ObjectPropertyBase.java:130), javafx.beans.property.ObjectPropertyBase.set(ObjectPropertyBase.java:163), javafx.scene.web.WebEngine$LoadWorker.updateState(WebEngine.java:975), javafx.scene.web.WebEngine$LoadWorker.dispatchLoadEvent(WebEngine.java:1086), javafx.scene.web.WebEngine$LoadWorker.access$600(WebEngine.java:968), javafx.scene.web.WebEngine$PageLoadListener.dispatchLoadEvent(WebEngine.java:955), com.sun.webpane.platform.WebPage.fireLoadEvent(WebPage.java:2356), com.sun.webpane.platform.WebPage.fwkFireLoadEvent(WebPage.java:2204), com.sun.webpane.webkit.network.URLLoader.twkDidFinishLoading(Native Method), com.sun.webpane.webkit.network.URLLoader.access$1300(URLLoader.java:44), com.sun.webpane.webkit.network.URLLoader$6.run(URLLoader.java:691), com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:76), com.sun.glass.ui.win.WinApplication._runLoop(Native Method), com.sun.glass.ui.win.WinApplication.access$100(WinApplication.java:17), com.sun.glass.ui.win.WinApplication$3$1.run(WinApplication.java:67), java.lang.Thread.run(Thread.java:744)]
包含javascript代码的html页面经过了充分测试。我们假设那里没有javascript错误
错误netscape.javascript.JSException: ReferenceError: Can't find variable: gotoLatLng
并不会发生在我身上,因为在loadWorker的newState == State.SUCCEEDED之后执行了javascript代码。
问题在于,在我的同事程序的堆栈跟踪中,我们可以看到WebEngine.executeScript(WebEngine.java:811)
被调用
packagename.WebMap.promise.Deferred.resolve(Deferred.java:40), packagename.WebMap.WebMap$2.changed(WebMap.java:57), packagename.WebMap.WebMap$2.changed(WebMap.java:52), com.sun.javafx.binding.ExpressionHelper$SingleChange.fireValueChangedEvent(ExpressionHelper.java:196), com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:100),
因此,当load changed event
时,newState == State.SUCCEEDED
的监听器会调用executeScript,这意味着页面已完全加载并且加载了s中的javascript(应该定义变量)。
很抱歉,因为我无法访问我的同事代码,但它基于我的代码。现在我不确定这段代码是否在适当的时候执行javascript代码
webEngine.getLoadWorker().stateProperty().addListener(
new ChangeListener<State>() {
@Override
public void changed(ObservableValue ov, State oldState, State newState) {
if (newState == State.SUCCEEDED) {
webEngine.executeScript(script);
}
}
}
);
任何帮助?
答案 0 :(得分:2)
怎么样
$(function(){
alert("command:ready");
});
然后
engine.onAlert = new EventHandler<WebEvent<String>>() {
@Override
void handle(WebEvent<String> event) {
if("command:ready".equals(event.getData())){
//TODO: initialize
}
}
}