1

With our web application, a call to the server using ajax with a 'kill' operation attached must be made when the user exits/closes the window. However, either the unload/pagehide event is not being fired, or the ajax call is not being executed and I have been unable to determine as to why...

Context:

  • Unfortunately, we must use vanilla js; no jQuery.
  • I am well aware of onbeforeunload, but for various cases, the ajax call cannot occur within that event (unless there is some magical hack that I am not aware of that suppresses the default popup box and/or provides a way to see user response).
  • We must have compatibility for IE7+, FF14+. No need to support Chrome, Safari, Opera.
  • I know the ajax functionality works - it is called numerous times while the browser is active and has been thoroughly tested.

Relevant code...

Code from the .jsp:

if (window.onpagehide || window.onpagehide === null) {
    addEvent(window, 'pagehide', kill);
} else {
    addEvent(window, 'unload', kill);
}

Code from utils file:

function addEvent(obj, evt, fnc) {

    if (obj.addEventListener) { //W3C
        obj.addEventListener(evt, fnc, false);
        return true;
    } else if (obj.attachEvent) { // MSFT
        return obj.attachEvent('on' + evt, fnc);
    } else { // Legacy

        evt = 'on'+evt;

        if(typeof obj[evt] === 'function') {

            // Object already has a function on traditional
            // Let's wrap it with our own function inside another function
            fnc = (function(f1, f2) {
                return function() {
                    f1.apply(this, arguments);
                    f2.apply(this, arguments);
                }
            })(obj[evt], fnc);
        }

        obj[evt] = fnc;
        return true;
    }

    return false;
};

    function kill() {

        ajax.post({
            "refCallback": null,
            "sURL": "--deleted--",
            "async": false,
            "timeout": 10000,
            "params": {"op": "kill",
                        "guid": guid}});

    };

Any insight or pointers will be extremely helpful...

bcwebb88
  • 299
  • 1
  • 5
  • 16

2 Answers2

0

It's been awhile since I've messed with onunload and onbeforeunload, but this is what I remember. When trying to use the onunload, you have a very short amount of time to do anything because the request to unload the page is already in progress. Typically, you need to execute your code inside of the onbeforeunload method. As to your question on "unless there is some magical hack that I am not aware of that suppresses the default popup box and/or provides a way to see user response", there is a way to suppress the default popup box, but if your intention is to replace it with a custom one, you're out of luck. To make the popup box not appear, simply don't return anything in the onbeforeonload call.

I remember I needed to do something very similar to what you're asking. I also couldn't use JQuery, but I used a call to a jsp to drop credentials instead of using AJAX. I actually asked the question on Stack Overflow and answered it myself: How to logout during onbeforeunload/onunload using Javascript. Try replacing my jsp call with your AJAX call?

Below is a good skeleton example of unbeforeunload compared to onunload:

<script type="text/javascript"> //may not be neccesary for your code

window.onbeforeunload=before;
window.onunload=after;

function before(evt)
{
   return "This will appear in the dialog box allong with some other default text";
   //If the return statement was not here, other code could be executed silently (with no pop-up)
}

function after(evt)
{
   //This event fires too fast for the application to execute before the browser unloads
}

</script>

The above code was a result of an answer I had, to what I feel, is a similar question at Show popup window when the browser close and OnUnload Alert Error "NS_ERROR_NOT_AVAILABLE".

Even though you'd be using the onbeforeunload instead of the onunload, if I remember correctly, it won't finish executing lengthy code if you don't display the popup. I know this answer isn't directly what you're looking for, but hopefully it leads you to the right path.

Community
  • 1
  • 1
Brian
  • 529
  • 2
  • 7
  • 17
  • I suspected the resources were being unloaded, but I was hoping that a quick ansyc ajax call would be made prior to those resources being unloaded. I ended up implementing a work around that works (just slightly less elegant). Thanks for confirming/answering! – bcwebb88 Mar 17 '14 at 01:33
-1

In fact it is possible to do AJAX request in pagehide or unload (deprecated but still working) event handler but you need to make this request synchronous, otherwise request will just be thrown away by Safari.

window.addEventListener("pagehide", function(evt){
  var request = new XMLHttpRequest();
  request.open('GET', '/bar/foo.txt', false);  // `false` makes the request synchronous
  request.send(null);

  if (request.status === 200) {
    // your request has been sent
  }
}, false);
Julien Bachmann
  • 753
  • 8
  • 18