javascriptjavaseleniumbrowser-automationjavascript-injection

JavascriptExecutor SyntaxError: Unexpected identifier. Why?


Java

JavascriptExecutor js = (JavascriptExecutor) driver;
Boolean ready = (Boolean)js.executeScript("the below JavaScript");

JavaScript

var ready = false;
window.onload = function() {
    ready = true;
}
window.sleep = function() {
    return new Promise(resolve => setTimeout(resolve, 2000));
}
for(var i = 0; i < 30; i++) {
    if(ready) {
           return true;
    }
    await sleep();
 }
 return false;

UPDATE: Sorry about the previous syntax error "funtion" in my post. That was a typo not in my actual code. All syntax errors should be gone, but I still get "SyntaxError: Unexpected identifier".

What this code is trying to do is wait for a maximum amount of time for the page to be loaded. I typically return document.readyState to check for that condition but in unique circumstances Chrome will suddenly stop loading the page and document.readyState hangs for 5+ minutes. This is killing my code so I am attempting to develop single-threaded code to kind of mimic a typically multi-threaded process.

Since JavaScript is single threaded (such a disappointing feature for a cool language like JavaScript), we have to be creative.

This code works in the browser console if you replace return true; with console.log('true'); and return false; with console.log('false'); so I don't see what the problem is.


Solution

  • Indeed there are some mistakes in your JavaScript code.

    The first mistake is, in third line window.sleep = funtion() { return new Promise(resolve => setTimeout(resolve, 2000)); }, the function spelling is wrong.

    The second mistake is you should not use await when there is no async in your function definition. Here is the thing, async ensures that the function returns a promise, and wraps non-promises in it. The keyword await makes JavaScript wait until that promise settles and returns its result. await works only inside async functions. So you can avoid using these completely or you need to format it accordingly.

    The third mistake is, you are trying to do return true; from the for loop of the if condition which is not allowed basically because it is not wrapped inside the function.

    The fourth mistake is, you are not calling the window.onload function - as the result, it is always returns false even though the page is loaded.

    The fifth thing is, I don't know what incomplete resolve is doing in window.sleep function.

    The sixth thing is, you are returning return false; at the end without any reference which is completely meaningless.

    I have modified the code and avoided the above mistakes, please look into it.

    Below is the modified JavaScript code:

    var status = false;
    window.sleep = function() { 
        return setTimeout(() => {
            console.log("=> Waited for 2 seconds...");
        }, 2000);
    }
    var getStatus = function() {
        for(var i = 0; i < 30; i++) {
            if(window.onload = function() {
                return true;
                }) {
                status = true;
                console.log(i+"). Loaded ? "+status);
                break;
            } else {
                console.log(i+"). Loaded ? "+status);
                sleep();
            }
        }
        return status;
    }
    getStatus();
    

    Try the below Java code which prints true after the page loads :

    System.setProperty("webdriver.chrome.driver", "C:\\NotBackedUp\\chromedriver.exe");
    WebDriver driver = new ChromeDriver();
    driver.get("http://www.google.com");
    JavascriptExecutor js = (JavascriptExecutor) driver;
    Boolean result = (Boolean) js.executeScript("var status = false;\r\n" + 
            "window.sleep = function() { \r\n" + 
            "   return setTimeout(() => {\r\n" + 
            "       console.log(\"=> Waited for 2 seconds...\");\r\n" + 
            "   }, 2000);\r\n" + 
            "}\r\n" + 
            "var getStatus = function() {\r\n" + 
            "   for(var i = 0; i < 30; i++) {\r\n" + 
            "       if(window.onload = function() {\r\n" + 
            "           return true;\r\n" + 
            "           }) {\r\n" + 
            "           status = true;\r\n" + 
            "           console.log(i+\"). Loaded ? \"+status);\r\n" + 
            "           break;\r\n" + 
            "       } else {\r\n" + 
            "           console.log(i+\"). Loaded ? \"+status);\r\n" + 
            "           sleep();\r\n" + 
            "       }\r\n" + 
            "   }\r\n" + 
            "   return status;\r\n" + 
            "}\r\n" + 
            "return getStatus();");
    System.out.println(result);
    

    I hope it helps...