Search code examples
javascriptjavagwtxmlhttprequestjsni

JSNI - $wnd.location.assign() not triggering immediately


I have the following JSNI code in my GWT app that makes an HTTP request to detect a URL redirect -

private native void checkSession(String url)
    /*-{
            var xhr = new XMLHttpRequest();
            xhr.onreadystatechange = function(e) {
                if (xhr.readyState == 4) {
                    if (url != xhr.responseURL) {
                        $wnd.alert("Your session has timed out.");
                        $wnd.location.assign(url);
                    }
                }
            }
            xhr.open("GET", url, true);
            xhr.send();
    }-*/;

If the URL requested is not the same as the response URL, the session is deemed to be timed out; upon which I want to display an alert box letting the user know that the session has timed out, and initiate a redirect when they click on OK.

I have a custom class that implements AsyncCallback. Using this technique, I was able to globally enforce onFailure() to call checkSession() whenever a StatusCodeException occurs.

The problem is that the alert box pops up several times before $wnd.location.assign(url) can initiate the redirect. I realize that several onFailure() methods are being executed here causing the alert to pop up several times, but my question is, why is $wnd.location.assign(url) not being executed until the last onFailure() method is executed, while $wnd.alert() which is right above it, being executed every single time?

How can I force a redirect in this situation? Ideally, I want the alert to pop up once, and redirect immediately upon OK being clicked.


Solution

  • According to this answer, the browser will try to execute the remaining JavaScript code until the page is redirected; which explains the occurrence of multiple alerts before the page redirects.

    To get around this, I declared private static boolean redirect = false;. When a URL redirect is detected within the JSNI code, I check if redirect is false, and if it is, I display the alert and set redirect = true -

    if (@fully.qualified.name::redirect == false) {
           @fully.qualified.name::redirect = true;
           $wnd.alert("Your session has timed out.");
    }
    $wnd.location.assign(url);
    

    That way, I was able to show the alert only once before initiating a redirect.