如何检查浏览器中是否有待处理请求(Ajax及其变体)

21

我处理的一些网站有大量的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请求或任何类似的替代方法。

这些测试都不是我编写的,也不属于单个Web应用程序。因此我无法编辑该Web应用程序。


如果使用其他库(如vanilla)发送异步请求,jquery.active是否仍然有效?如果不是,那么我问错了问题。 - raju
如果您的应用程序不使用jQuery,那么将其注入到应用程序中就没有任何意义。 - Purus
https://github.com/sebuilder/se-builder/issues/188 提供了更多的上下文。 - raju
你能检查一下我下面发布的答案吗? - Purus
2
你有检查过这个 Stack Overflow 的问题吗: 如何检查浏览器中的 HTTP 请求是否打开? - LeGEC
显示剩余4条评论
4个回答

13

我找到了答案,并且它适用于我检查过的一些Ajax和非Ajax网站。在这个补丁之后,即使是对于ajax重负载的页面,我也不再需要进行隐式等待。LeGac在他的评论中指出了以下代码:

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);

6
你确定这是 JavaScript 吗?它看起来像 Java。 - Tebe
在 Angular 应用程序中,此脚本在浏览器控制台中给出以下警告,并且我的服务调用也失败了。 [Deprecation] 同步 XMLHttpRequest 在主线程上已被弃用,因为它对最终用户的体验有害。欲了解更多帮助,请访问 https://xhr.spec.whatwg.org/。 - Karthi
这很棘手。有时候页面在你的脚本运行之前已经触发了ajax。最好的方法是使用浏览器扩展程序。但这对Chrome Headless模式不起作用。 - Nicholas DiPiazza

2

不,它只适用于ajax,但请求可以是任何类型。 - raju

1

-3

根据我们在评论中的讨论,这可能适合您。

使用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();
    }
}

源代码:检查挂起的AJAX请求或HTTP GET/POST请求


对我来说不起作用。我已经检查了一个挂起的ajax请求。document.readyState始终是“complete”。请查看http://tinypic.com/r/mr4qis/8。即使存在挂起的ajax请求,document.readyState也是“complete”。 - raju

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接