等待主框架加载时出现 JxBrowser TimeoutException

我在一个项目中使用 JxBrowser。我只使用本地 HTML 文件,因此使用以下方法呈现我的 HTML 文件:


    public static void loadHTMLFile(Browser browser, String filename){

        String current = PathUtils.getCurrentDir();

        browser.loadURL("file:///" + current + "/some/path/in/my/project/resources/web/" + filename);

    } 

在某些情况下,我必须使用invokeAndWaitFinishLoadingMainFrame -方法,因为我必须初始化必须首先完全加载的按钮。


来自官方 JxBrowser 网站 ( https://jxbrowser.support.teamdev.com/support/solutions/articles/9000013107-loading-waiting ) 的示例如下所示:


// Blocks current thread execution and waits until http://www.google.com web page is loaded completely

Browser.invokeAndWaitFinishLoadingMainFrame(browser, new Callback<Browser>() {

    @Override

    public void invoke(Browser value) {

        value.loadURL("http://www.google.com");

    }

});

就我而言,它看起来像这样:


public static void loadHTMLFileComplete(Browser browser, String filename){

    Browser.invokeAndWaitFinishLoadingMainFrame(browser, new Callback<Browser>() {

        @Override

        public void invoke(Browser value) {

            loadHTMLFile(value, filename);

        }

    });

}

到目前为止,我想没有什么令人惊讶的......


现在是棘手的部分:


invokeAndWaitFinishLoadingMainFrame方法是问题所在:


使用invokeAndWaitFinishLoadingMainFrame -方法正确加载了第一个视图(登录视图)

之后,当再次 使用invokeAndWaitFinishLoadingMainFrame -方法时,我的程序超时(下面的完整异常)

例如,当我单击登录按钮并希望被转发到主视图时

有一个小技巧,我偶然发现让它暂时工作(现在它变得令人毛骨悚然):


当我在谷歌之间加载在线网页时,超时问题消失了

也可以使用invokeAndWaitFinishLoadingMainFrame -方法

我就是这样做的


public static void loadGoogle(Browser browser){

    Browser.invokeAndWaitFinishLoadingMainFrame(browser, new Callback<Browser>() {

    @Override

    public void invoke(Browser value) {

        value.loadURL("http://www.google.com");


    }

});

}


这里出现了我之前提到的 timeoutException:


-- Product name: JxBrowser

-- Licensed version: 6.x

-- Licensed to: 

-- License type: Evaluation

-- Generation date: 21.04.2019

-- Expiration date: 21.05.2019

-- License info: Single-user license

-- Current date: 30.04.2019

JxBrowser license valid.


胡子哥哥
浏览 74回答 1
1回答

翻过高山走不出你

JxBrowser 基于 Chromium 引擎,继承了其多进程架构。每个Browser实例与至少一个处理 DOM 和 JavaScript 相关功能的渲染进程相关联。当您导航到不同的域时,Chromium 引擎会创建一个新的渲染进程并终止旧的渲染进程。如果您在一个域内导航,则呈现过程保持不变。从调用堆栈中,我看到您尝试从 DOM 侦听器中加载 URL。DOM 侦听器是同步调用的,因此在 Java 处理事件时渲染进程保持阻塞。当你加载一个 URL 时,例如 google.com,一切正常,因为一个新的渲染进程被创建,并且一旦页面被加载,该Browser.invokeAndWaitFinishLoadingMainFrame方法返回控制并且旧的渲染进程被终止。但是,如果您尝试加载file:///URL,则渲染过程保持不变,并且无法开始加载,因为渲染过程被Browser.invokeAndWaitFinishLoadingMainFrameDOM 侦听器调用的方法阻塞,因此您会遇到死锁。为了避免此异常,您不应从 DOM 侦听器中启动同步导航。根据调用堆栈,您loadView从DOMEventListener. 为了避免死锁,您应该异步调用此方法,例如:import com.teamdev.jxbrowser.chromium.dom.events.DOMEvent;import com.teamdev.jxbrowser.chromium.dom.events.DOMEventListener;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class MyDomEventListener implements DOMEventListener {&nbsp; &nbsp; private final ExecutorService executorService;&nbsp; &nbsp; private final OrderCreationView view;&nbsp; &nbsp; public MyDomEventListener(OrderCreationView view) {&nbsp; &nbsp; &nbsp; &nbsp; this.view = view;&nbsp; &nbsp; &nbsp; &nbsp; this.executorService = Executors.newCachedThreadPool();&nbsp; &nbsp; }&nbsp; &nbsp; @Override&nbsp; &nbsp; public void handleEvent(DOMEvent domEvent) {&nbsp; &nbsp; &nbsp; &nbsp; // Do not block the current thread and invoke the loadView method asynchronously.&nbsp; &nbsp; &nbsp; &nbsp; executorService.execute(view::loadView);&nbsp; &nbsp; }}在该loadView方法中,您可以同步加载 HTML:public void loadView() {&nbsp; &nbsp; Browser.invokeAndWaitFinishLoadingMainFrame(browser, new Callback<Browser>() {&nbsp; &nbsp; &nbsp; &nbsp; @Override&nbsp; &nbsp; &nbsp; &nbsp; public void invoke(Browser browser) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; browser.loadHTML("");&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; });&nbsp; &nbsp; initLoginButton();}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java