3

I have a Flex client application. I need a clean up function to run in Flex when the user closes the browser. I found the following solution on the net, but it only works half-way for me. How could I fix it? Thanks in advance for any responses!

Symptoms

  • CustomEvent triggered, but not executed.
    >> EventHandler for CustomEvent.SEND_EVENTS is defined by a Mate EventMap. All the handler does is to call an HTTPServiceInvoker. In debug console, I'm able to see the handler and HTTPServiceInvoker being triggered, but neither the resultHandlers nor the faultHandlers were called. I know this event handler has no problem because when I dispatch the same CustomEvent.SEND_EVENTS in a button click handler, it behaves exactly as I expected)
  • Browser seems to wait for cleanUp function to complete before it closes. (all traces were printed before browser closes down)

Code

I added the following into the index.template.html

window.onbeforeunload = clean_up;

function clean_up()
{
 var flex = document.${application} || window.${application};
 flex.cleanUp();
}

And used the following in the application MXML file

import flash.external.ExternalInterface;

public function init():void {
ExternalInterface.addCallback("cleanUp",cleanUp);
}

public function cleanUp():void {   

   var newEvent:CustomEvent = new CustomEvent(CustomEvent.SEND_EVENTS);
   newEvent.requestObj = myFormModel;

   dispatchEvent(newEvent);

   // for testing purposes
   // to see whether the browser waits for Flex cleanup to finish before closing down   
   var i:int;
   for (i=0; i<10000; i++){
        trace(i);
   }    

}

My Setup

  • FlexBuilder 3
  • Mate MVC Framework (Mate_08_9.swc)
  • FlashPlayer 10
tomato
  • 5,644
  • 13
  • 43
  • 48

3 Answers3

2

Unfortunately, there is no solid way of doing such clean up functions that execute asynchronously. The result/fault events of the HTTPService occur asynchronously after the cleanUp method is returned. The browser waits only till the onbeforeunload function (the js clean_up function) returns. Unless you call event.preventDefault() from that function, the page will be closed. Note that calling preventDefault() will result in an ok/cancel popup asking:

Are you sure you want to navigate away from this page?

Press OK to continue, or Cancel to stay on the current page.

If the user selects OK, the browser will be closed nevertheless. You can use the event.returnValue property to add a custom message to the popop.

//tested only in Firefox
window.addEventListener("beforeunload", onUnload, false);
function onUnload(e)
{
   e.returnValue = "Some text that you want inserted between " +
     "'Are you sure' and 'Press OK' lines";
   e.preventDefault();
}
Amarghosh
  • 58,710
  • 11
  • 92
  • 121
  • so, there is no way to ensure that the cleanup is finished, because there is no way to prevent the user to select 'ok'?? – tomato Oct 30 '09 at 23:50
1

You'll never be able to reliably detect the browser code 100% of the time. If you really need to run actions then the safest course of action is to have clients send "i'm still alive" messages to the server. The server needs to track time by client and when a client doesn't send a message within the specified amount of time (with some wiggle room), then run clean-up activities.

The longer you make the time the better, it depends on how time-critical the clean-up is. If you can get away with waiting 5 minutes that's great, otherwise look at 1 minute or 30 seconds or whatever is required for your app.

Samuel Neff
  • 73,278
  • 17
  • 138
  • 182
  • thanks for the answer. this is a different approach to the problem, will keep this in mind... – tomato Oct 30 '09 at 23:52
1

An alternate way to clean up the session on client side is to use JavaScript and external.interface class in as3. Here is sample code:

JavaScript:

function cleanUp()
{

    var process;
    var swfID="customRightClick";
    if(navigator.appName.indexOf("Microsoft") != -1){
        process = window[swfID];
        }else
    {
        process = document[swfID];
    }
    process.cleanUp();
}

and in the as3 class where the clean up function is defined use this:

import flash.external.ExternalInterface;

if (ExternalInterface.available)
{
    ExternalInterface.addCallback("cleanUp", cleanUp);
}

function cleanUp():void {// your code }
Jason Plank
  • 2,336
  • 5
  • 31
  • 40
intoTHEwild
  • 448
  • 7
  • 24
  • This is a nice way of cleaning up the session on client-side. Thanks. :) Unfortunately, it doesn't apply to my case, because I'm trying to trigger something on the server-side through HTTP request, when the user closes the browser. I could do it this way, but the key to my problem is still how to ensure my HTTP request has completed by the time the browser shuts down. – tomato Nov 02 '09 at 22:22