How to checkif there are pending requests (Ajax and its variants) from browser

前端 未结 4 1974
感动是毒
感动是毒 2020-12-28 16:20

Some of the sites I deal with have heavy ajax requests. I plan to wait for Ajax request completion before clicking for asserting for element. Currently I use



        
相关标签:
4条回答
  • 2020-12-28 16:50

    I found the answer and it worked for few Ajax and non-ajax sites I checked. After this patch I no longer need to do implicit waits even for ajax heavy pages, LeGac pointed out the following code in one of his comments to the question.

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

    After every step you would need to call

    checkPendingRequests(driver);
    
    0 讨论(0)
  • 2020-12-28 16:53

    This doesn't work? http://api.jquery.com/ajaxstop/

    $(document).ajaxStop(function() {
        // Do stuff here...    
    });
    
    0 讨论(0)
  • 2020-12-28 17:07

    If you are using JSONP requests, you need to enable the active handling:

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

    I think that the use of active is correct, but possibly the way you have used might return false in the instanceof conditions.

    Optionally, 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')
    
    0 讨论(0)
  • 2020-12-28 17:07

    Based on our discussion over the comments, this might work for you.

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

    With plain script:

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

    Source: Check Pending AJAX requests or HTTP GET/POST request

    0 讨论(0)
提交回复
热议问题