【问题标题】:HTMLUnit doesn't wait for JavascriptHTMLUnit 不等待 Javascript
【发布时间】:2011-04-05 16:28:24
【问题描述】:

我有一个基于 GWT 的页面,我想使用 HtmlUnit 为其创建一个 HTML 快照。 该页面使用产品上的 Ajax/JavaScript 信息加载,因此在大约 1 秒钟内出现 Loading... 消息,然后显示内容。

问题是 HtmlUnit 似乎没有捕获信息,我得到的只是“正在加载...”跨度。

下面是一个带有 HtmlUnit 的实验代码,我尝试给它足够的时间来等待数据的加载,但它似乎没有改变任何东西,我仍然无法捕获 GWT javascript 加载的数据。

        WebClient webClient = new WebClient();
        webClient.setJavaScriptEnabled(true);
        webClient.setThrowExceptionOnScriptError(false);
        webClient.setAjaxController(new NicelyResynchronizingAjaxController()); 

        WebRequest request = new WebRequest(new URL("<my_url>"));
        HtmlPage page = webClient.getPage(request);

        int i = webClient.waitForBackgroundJavaScript(1000);

        while (i > 0)
        {
            i = webClient.waitForBackgroundJavaScript(1000);

            if (i == 0)
            {
                break;
            }
            synchronized (page) 
            {
                System.out.println("wait");
                page.wait(500);
            }
        }

        webClient.getAjaxController().processSynchron(page, request, false);

        System.out.println(page.asXml());

有什么想法吗...?

【问题讨论】:

    标签: java ajax gwt htmlunit


    【解决方案1】:

    感谢您的回复。 实际上,我应该早点报告这一点,因为我自己找到了解决方案。 显然在用 FF 初始化 WebClient 时:

    WebClient webClient = new WebClient(BrowserVersion.FIREFOX_3_6);
    

    它似乎正在工作。 使用默认构造函数初始化 WebClient 时,它默认使用 IE7,我猜 FF 对 Ajax 的支持更好,是推荐使用的模拟器。

    【讨论】:

    • 我必须对此发表评论。遇到了同样的问题,正在尝试调试整个代码。非常感谢。
    • 嗨。我有同样的问题,尽管 IE 使用 FIREFOX 使页面现在几乎正常加载,但我仍然坚持 ...Loading... 消息,应该大约 9 秒,也使用了你的部分代码和没什么:(请帮忙
    • 谢谢!在找到您的评论之前,我在调试过程中损失了几个小时!
    【解决方案2】:

    我相信默认情况下NicelyResynchronizingAjaxController 只会通过跟踪它来自哪个线程来重新同步由用户操作引起的 AJAX 调用。也许 GWT 生成的 JavaScript 正在被 NicelyResynchronizingAjaxController 不想等待的其他线程调用。

    尝试声明您自己的 AjaxController 以与所有内容同步,而不考虑原始线程:

    webClient.setAjaxController(new AjaxController(){
        @Override
        public boolean processSynchron(HtmlPage page, WebRequest request, boolean async)
        {
            return true;
        }
    });
    

    【讨论】:

      【解决方案3】:

      如文档所述,waitForBackgroundJavaScript 是实验性的:

      实验性 API:可能会在下一个版本中更改,可能还不能完美运行!

      无论使用什么BrowserVersion,下一个方法一直对我有用:

      int tries = 5;  // Amount of tries to avoid infinite loop
      while (tries > 0 && aCondition) {
          tries--;
          synchronized(page) {
              page.wait(2000);  // How often to check
          }
      }
      

      注意aCondition 是您要检查的任何内容。例如:

      page.getElementById("loading-text-element").asText().equals("Loading...")
      

      【讨论】:

      • 到目前为止,像这样的轮询对我来说也很有效。
      【解决方案4】:

      目前提供的解决方案都不适合我。我最终得到了Dan Alvizu's solution + 我自己的 hack:

      private WebClient webClient = new WebClient();
      
      public void scrapPage() {
          makeWebClientWaitThroughJavaScriptLoadings();
          HtmlPage page = login();
          //do something that causes JavaScript loading
          waitOutLoading(page);
      }
      
      private void makeWebClientWaitThroughJavaScriptLoadings() {
          webClient.setAjaxController(new AjaxController(){
              @Override
              public boolean processSynchron(HtmlPage page, WebRequest request, boolean async)
              {
                  return true;
              }
          });
      }
      
      private void waitOutLoading(HtmlPage page) {
          while(page.asText().contains("Please wait while loading!")){
              webClient.waitForBackgroundJavaScript(100);
          }
      }
      

      不用说,“加载中请稍候!”应替换为页面加载时显示的任何文本。如果没有文本,也许有一种方法可以检查某些 gif 是否存在(如果使用的话)。当然,如果您喜欢冒险,您可以简单地提供足够大的毫秒值。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-02-22
        • 2014-10-27
        • 1970-01-01
        • 1970-01-01
        • 2021-09-15
        • 1970-01-01
        相关资源
        最近更新 更多