Can the unload Event be Used to Reliably fire ajax Request?
Asked Answered
C

5

36

I need a method to monitor user edit sessions, and one of the solutions I'm reviewing will have me using an unload event to send an ajax request to inform the server of the end of the edit session. (See: Monitoring User Sessions to Prevent Editing Conflict)

My (rather limited) reading on the unload event indicates that the code attached to this handler has to run quickly, and as such, is usually used for clearing objects to prevent memory leaks.

My question is, can this work reliably enough for this purpose?

PS. I know about the async: false option.

Crassulaceous answered 27/8, 2010 at 12:51 Comment(0)
C
36

This method is fairly reliable, if your server is fast enough to respond. Something to really watch out for though. If you close the browser and send AJAX request on unload event, there's a very good chance that the response isn't going to come back from the server in time before the window object is destroyed. What happens in this case (at least with IE) is that it will orphan your connection object and not terminate it correctly until the connection timeout is hit. If your server doesn't have connection keep-alive turned on, after you close 2 windows (while still having another window open), you will run out of open connections to the server (for IE6-7, for IE8 - 6 windows) and you will not be able to open your website until your connection timeout is hit.

I ran into a situation like that before were I was opening a popup window that was sending an AJAX request on unload, it was very reliable, but it was plagued by the issued described above, and it took really long time for me to track it down and understand what's going on. After that, what I did, is I made sure that opening window would have the same code to call server, and on every unload checked for the opener and ran the code there if it was present.

It seems that if you close the very last browser window, IE will destroy connection properly, but if one other window is open, it will not.

P.S. And just to comment on the answer above, AJAX is not really async. At least JS implementation of it isn't. After you send a request, you JS code is still going to be waiting for response from the server. It's not going to block your code execution, but since the server might take a while to response (or long enough for Windows to terminate IE window object) you might and probably will run into the problem described above.

Cordy answered 29/8, 2010 at 19:24 Comment(5)
Has anyone tried this with async turned off? I'm guessing that this would prevent the browser from unloading until the request returned.Arlindaarline
That's correct. With async turned off the browser will wait for response from the server before unloading the page. This helps with Chrome bug, where Chrome is very unreliable when it comes to unload event and async operations. This will also fix IE connection hogging that I described above. But it will be user visible.Cordy
It's worth keeping an eye on the new Beacon API with Navigator.sendBeacon that will allow a better way to reliably issue an asynchronous request to our server on unload: developer.mozilla.org/en-US/docs/Web/API/Navigator/sendBeaconPaolo
Synchronous requests are deprecated, calling ajax with async:false will stop working in the future. developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest search for asyncBarthol
Synchronous request support has removed from Chrome from version 82.Phira
I
12

Have you tried to use

var i = new Image(1,1); 
i.src='http://...'

And just returning some empty image from server. I think it should be reliable, script will block. BTW: nice to add timestamp to prevent caching.

Ironstone answered 25/12, 2010 at 18:58 Comment(1)
I found that AJAX calls in the onload event function did not work, but this method did. It should be noted that the function code does not stop or block the page unload, the code may execute after the page has unloaded.Counsel
B
3

We have a case where we needed that. It's a report page that needs serious memory on the server so we wanted to free it immediately as soon as they left the page. We created a frameset and added the unload handler there. The most reliable way was to set the src of an image to the freeing script. We actually used both the unload and onbeforeunload for cross browser compatibility. It didn't work in web kit nightlies but management was OK with that.

However, that was not my proposed solution. I would use a heartbeat approach which involves more work but is much more robust.

Your page should send out periodical heartbeat requests. Each request sets the last heartbeat from a page. You then need a thread that runs on the server and clears memory if the last heartbeat was too long ago.

This doesn't solve the problem of leaving the page up for a long time. For that you need some monitoring for user activity and leave that page after a period of inactivity (make sure you confirm with the user)

Barthol answered 27/8, 2010 at 17:37 Comment(2)
Do you really need the frameset , image and freeing script method? It seems rather hackish... Or was that a lot more reliable compared to using the two unload events?Crassulaceous
We needed the frameset because there was navigation going on within the page, we only wanted to send the "free-memory" request when navigating away from the set of pages. The image/two-unload method was the way we got it to run most reliably across browsers and OSs.Barthol
D
1

You'll have to do your own testing about whether or not your particular scenario works with the time you have in unload, but making the AJAX request is pretty fast, since AJAX is asynchronous. You just send the request and then you're done! (Maybe you'll have to clear the request object you just created, though.)

If you wanted to verify that the AJAX request made it, then you'd have to worry more/use the async:false option (like this discussion indicates). But, just sending is a quick boom-and-you're-done operation.

Dysphemism answered 27/8, 2010 at 15:47 Comment(2)
Well, I won't call it reliable if it can't reach the server, right? ;)Crassulaceous
True, but I thought you meant reliable in that the browser will actually send the request.Dysphemism
H
-2

I had a case in which I only needed to notify server side about the unload and didn't care about the response.

If thats your case you can ignore_user_abort and then you know it'll happen "reliably"

Hrutkay answered 2/7, 2014 at 8:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.