waiting for callback asynchronous java-script in java Selenium JavaScriptExecutor

Firstly to address the obvious

I’ve seen a million and one questions on this with the main dupe target being:
How do I return the response from an asynchronous call?
This does not suit my needs because

A: I know that I need Asynchronous java-script already and that I want to use callback functions. I need details on HOW to implement them properly with specific conditions (in Selenium using JavascriptExecutor ect) that I wasn’t able to glean from the other questions

B: that question is more specific to Ajax which makes it extremely confusing for me to gain anything from it.

C: this is more about the best way to wait for asynchronous calls like this to complete

What I’ve done besides Stack overflow research

I also went to many websites including:
https://www.sitepoint.com/callbacks-javascript/
Which gave me some basic insight on how callbacks are implemented and I’ve implemented one correctly
I also found this website
https://javapapers.com/ajax/getting-started-with-ajax-using-java/
Which gave me basic insight on one way I can think of to ‘wait’ for an asychronous javascript function to execute, that is to send over ajax data back to my code when the function is finally done.

What rabbit hole did you go down?

I want to make a simple script to determine whether a given web-element causes a page to reload. To do that I need a page load event. I researched awhile and found (through multiple questions on here) the JavascriptExecutor and the load event. I tried to implement them and I was naively thinking it would be an easy return statement. Originally I was trying to return the result of adding an event listener when I first tried implementing this. Then I figured out that was silly so I needed to get some sort of return value, I tried for a couple hours to return various parts of the add event listener script before I realized I was using the wrong approach and thinking about the problem wrong. Then I did this research on asynchronous JavaScript because asking questions about NPEs from my previous approach led me to it, what it is, how its used, and then I came across callback functions. After posting this and doing more research I correctly implemented a simple asynchronous callback function. Now I just need to properly wait for it to complete before moving forward so I know that the page is fully loaded.

an overarching description of what I’m doing

I have a thread off of main. This thread clicks a web-element. The clicked web-element has 3 basic cases I want to document/flag for:

  1. clicking it doesn’t reload the page and doesn’t move/get deleted (locators remain the same)
  2. clicking it doesn’t reload the page but the element locators (think ‘id’ get deleted or changed)
  3. clicking the web element causes a page reload

In order to document these three cases I need flags for, the on-load event and the stale-reference exception event and I want a timeout if both those don’t happen in time. If on-load happens then we know its case 3, in stale-reference happens but on-load doesn’t happen.

To get a flag for the stale-reference case was easy, its already in Selenium. The problem is the flag for the on-load event. To flag this I need something I can run in JavaScriptExecutor that then transfers data via asynchronous callback functions and possibly ajax (or some other method I’m open to suggestions) to java. This data can be as simple as a number, as long as I can get some message from the javascript telling my java that it’s done doing its asynchronous stuff. I’ve implemented a callback function in my code but I need to get data from the javascript to the java. Additionally it is really hard to test for syntax/errors in the javascript because I can’t just test the JavaScript script string itself as its own program easily (So far I’ve had to use free online editors that aren’t that good).

The code in question

//initialize a wait object and set a default timeout (the value is ten 
//seconds)
WebDriverWait wait = new WebDriverWait(driver,timeoutSeconds);
        try{
            //wait until stalereference exception is thrown (unless timeout 
            //is exceeded)
            wait.until(ExpectedConditions.stalenessOf(webElement));

            //define the test function with a callback inside it. Prints 2 
            //to a page on page reload event only if the webelement went 
            //stale
            String script = "function test(arg,callback) {callback(arg);}" +
                    "function Return(arg){document.write(arg);}" +
                    "var a = 2;" +
                    "window.addEventListener('load', test(a,Return));";
            //TODO change this fucntionality to use ajax or some other good 
            //method to say "hey I'm done executing!" to the java code

            //execute the script to add the event listener
            JavascriptExecutor js = (JavascriptExecutor)driver;
            js.executeScript(script);

            //flag the state of this Thread
        }
        //Timeout was exceeded so the page doesn't change on click
        catch (TimeoutException e){
            //here I set a 'page didn't change' flag
        }

Notes on the code/what I need codewise

The only things required to run this should be a web element, a driver object and maybe some print statements to be the ‘flags’. I used the chrome-driver driver because I like chrome and I’m using the question box as the webElement (and of course deleting my comments). My styling and syntax is probably messy but this is just test code at this point I want to get it functional. What I want is basically a

InsideCallback.POST(somedata) to java

But in code that works with (or replaces) my current test code. I know that since its asynchronous I don’t want to poll the return result (that defeats the purpose of the whole being asynchronous thing). I just don’t know how to say ‘when this function in another language returns its stuff’ in code. Unfortunately I don’t have a specific error with a stack-trace because its more about whats NOT in the code. I feel like I’m on the right path but I need to know if Ajax is the right way to go. The problem is, the workable examples of this seem complicated and might take awhile so I want to know what I’m getting into.

EDIT 1

Updated code so it shouldn’t have syntax errors that cause stacktrace/failure, it ran fine when I tried it, just some parenthesis mixup and argument syntax that was wrong. I still am missing some way to actually callback the callback function but I’m going to continue trying to research it.

Edit 2

OK I finally figured out javascript syntax enough and got it so that the eventlistener callback function stuff is working. I have it printing 2 to a page on a reload. Simple and easy. Now I just need to change that functionality to link to my javacode and set a simple flag of some sort. (updated code so when ran it should work much better). Updated code ordering to more closely match desired behavior. staleReferenceException should be aited for BEFORE the eventListener for onload event is added Otherwise the onload events fires prematurely for desired behavior.

Edit 3

Updated question to more accuractely reflect title/current status of research.

108 thoughts on “waiting for callback asynchronous java-script in java Selenium JavaScriptExecutor”

  1. After going over a handful of the articles on your blog, I seriously appreciate your technique of writing a blog.
    I book marked it to my bookmark website list and will be checking
    back soon. Please check out my web site as well and let me
    know your opinion.

    Reply

Leave a Comment