【问题标题】:How to checkif there are pending requests (Ajax and its variants) from browser如何检查是否有来自浏览器的待处理请求(Ajax 及其变体)
【发布时间】:2014-08-09 12:55:25
【问题描述】:

我处理的一些网站有大量的 ajax 请求。我计划在单击断言元素之前等待 Ajax 请求完成。目前我使用

try {
    if (driver instanceof JavascriptExecutor) {
        JavascriptExecutor jsDriver = (JavascriptExecutor)driver;

        for (int i = 0; i< timeoutInSeconds; i++) 
        {
            Object numberOfAjaxConnections = jsDriver.executeScript("return jQuery.active");
            // return should be a number
            if (numberOfAjaxConnections instanceof Long) {
                Long n = (Long)numberOfAjaxConnections;
                System.out.println("Number of active jquery ajax calls: " + n);
                if (n.longValue() == 0L)  break;
            }
            Thread.sleep(1000);
        }
    }
    else {
       System.out.println("Web driver: " + driver + " cannot execute javascript");
    }
}
catch (InterruptedException e) {
    System.out.println(e);
}

但它适用于 Ajax 请求,但不适用于任何具有 jQuery 库变体的类似请求。

注意:

document.readyState == 'complete'

它不适用于 Ajax 请求或任何其他类似的替代方案。

测试都不是由我编写的,也不属于单个 webapp。所以我无法编辑 webapp。

【问题讨论】:

  • 你的意思是你在其他网站的ajax调用是不用jquery的?注入jquery的目的是什么?
  • 问题是你为什么需要它
  • 如果使用 vanilla 等其他库发送异步请求,jquery.active 是否仍然有效?如果不是,那么我问错了问题。
  • 如果您的应用程序不使用 jquery,那么您没有任何将其注入应用程序的意义。
  • 你检查过这个 SO 问题吗:How to check if HTTP requests are open in browser?

标签: java jquery ajax selenium webdriver


【解决方案1】:

我找到了答案,它适用于我检查过的少数 Ajax 和非 ajax 网站。在这个补丁之后,我不再需要对 ajax 繁重的页面进行隐式等待,LeGac 在他的一个 cmets 中指出了以下代码。

public static void checkPendingRequests(FirefoxDriver driver) {
    int timeoutInSeconds = 5;
    try {
        if (driver instanceof JavascriptExecutor) {
            JavascriptExecutor jsDriver = (JavascriptExecutor)driver;

            for (int i = 0; i< timeoutInSeconds; i++) 
            {
                Object numberOfAjaxConnections = jsDriver.executeScript("return window.openHTTPs");
                // return should be a number
                if (numberOfAjaxConnections instanceof Long) {
                    Long n = (Long)numberOfAjaxConnections;
                    System.out.println("Number of active calls: " + n);
                    if (n.longValue() == 0L)  break;
                } else{
                    // If it's not a number, the page might have been freshly loaded indicating the monkey
                    // patch is replaced or we haven't yet done the patch.
                    monkeyPatchXMLHttpRequest(driver);
                }
                Thread.sleep(1000);
            }
        }
        else {
           System.out.println("Web driver: " + driver + " cannot execute javascript");
        }
    }
    catch (InterruptedException e) {
        System.out.println(e);
    }    
}



public static void monkeyPatchXMLHttpRequest(FirefoxDriver driver) {
    try {
        if (driver instanceof JavascriptExecutor) {
            JavascriptExecutor jsDriver = (JavascriptExecutor)driver;
            Object numberOfAjaxConnections = jsDriver.executeScript("return window.openHTTPs");
            if (numberOfAjaxConnections instanceof Long) {
                return;
            }
            String script = "  (function() {" +
                "var oldOpen = XMLHttpRequest.prototype.open;" +
                "window.openHTTPs = 0;" +
                "XMLHttpRequest.prototype.open = function(method, url, async, user, pass) {" +
                "window.openHTTPs++;" +
                "this.addEventListener('readystatechange', function() {" +
                "if(this.readyState == 4) {" +
                "window.openHTTPs--;" +
                "}" +
                "}, false);" +
                "oldOpen.call(this, method, url, async, user, pass);" +
                "}" +
                "})();";
            jsDriver.executeScript(script);
        }
        else {
           System.out.println("Web driver: " + driver + " cannot execute javascript");
        }
    }
    catch (Exception e) {
        System.out.println(e);
    }
}

每一步之后你都需要调用

checkPendingRequests(driver);

【讨论】:

  • 你确定是javascript吗?看起来像java
  • 在 Angular 应用程序中,此脚本在浏览器控制台中给出以下警告,并且我的服务调用也失败了。 [弃用] 主线程上的同步 XMLHttpRequest 已弃用,因为它会对最终用户的体验产生不利影响。如需更多帮助,请查看xhr.spec.whatwg.org
  • 这很活泼。您将在脚本运行之前页面已经触发 ajax 时获得时间。最好的方法是使用浏览器扩展。但这不适用于 Chrome Headless 模式。
【解决方案2】:

这行不通? http://api.jquery.com/ajaxstop/

$(document).ajaxStop(function() {
    // Do stuff here...    
});

【讨论】:

  • 不,它仅适用于 ajax,但请求可以是任何类型。
【解决方案3】:

如果使用JSONP请求,需要enable the active handling:

jQuery.ajaxPrefilter(function( options ) {
    options.global = true;
});

我认为active 的使用是正确的,但可能您使用的方式可能会在instanceof 条件下返回false。

(可选)see another way to wait for jQuery ajax calls using active in Selenium tests

browser.wait_for_condition("selenium.browserbot.getCurrentWindow().jQuery.active === 0;", '30000')

【讨论】:

    【解决方案4】:

    根据我们对 cme​​ts 的讨论,这可能对您有用。

    使用prototype.js:

    var ACTIVE_REQUESTS = 0; // GLOBAL
    
    ACTIVE_REQUESTS++
    new Ajax.Request('/your/url', {
      onSuccess: function(response) {
        ACTIVE_REQUESTS--;
        // Handle the response content...
      }
    }));
    
    console.log("there are " + ACTIVE_REQUESTS + " open AJAX requests pending");
    

    使用纯脚本:

    interValRef = 0;
    
    interValRef = setInterval("checkState();",100)
    
    function checkState(){
        if(document.readyState == 'complete'){
            clearInterval(interValRef);
            myFunc();
        }
    }
    

    来源:Check Pending AJAX requests or HTTP GET/POST request

    【讨论】:

    • 对我不起作用。我已经检查了一个待处理的 ajax 请求。 document.readyState 始终是“完整的”。结帐此tinypic.com/r/mr4qis/8。即使有未决的 ajax 请求,document.readyState 也是“完成”
    猜你喜欢
    • 2012-03-14
    • 1970-01-01
    • 2014-08-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-21
    相关资源
    最近更新 更多