Don't have time to send get request on window unload
Asked Answered
T

5

8

I want to notify the server on user closes browser window.

I tried all of the

$(window).bind("beforeunload", function() {
    $.get("${contextPath}/notify?direction=logout");
});

and

$(window).unload( function() {
    $.get("${contextPath}/notify?direction=logout");
});

and

$(window).unload(function() {
    $.ajax({
      url: "${contextPath}/notify?direction=logout"
    });
});

but neither work well, despite the fact, that it is said in manual that it probably should.

In Firefox I have no notifications only on window close, but have ones on page refresh. In Chrome I have neither.

I tried to trace this script in Firebug or Chrome Developer Tools and found, that it is starting to work if traced! So I think it does not work normally because it has no time to send request before window closed or navigated.

Is this true? How to accomplish my task?

Tequila answered 10/2, 2012 at 22:16 Comment(2)
First thought: AJAX is the wrong tool for the job. You should be using SJAX (synchronous), AJAX by definition releases the GUI thread to continue processing [in this case unload].Psychomotor
Check out this answer: https://mcmap.net/q/1321730/-php-javascript-do-something-when-user-closes-page-or-browser-duplicateMebane
P
4

It is very tricky because the browser will not wait untill the response comes so the ajax request might get aborted.

You can try something like this in beforeunload event.

$(window).bind("beforeunload", function() {
    $.ajax({
        async: false,//This will make sure the browser waits until request completes
        url: "${contextPath}/notify?direction=logout"
    });
});
Parabolic answered 10/2, 2012 at 22:22 Comment(1)
That's unreliable and while you can "try" that and it may work, it should never be used on a production environment.Wilder
V
26

The other answers are out of date, and cause other issues, such as unreliable signalling or delaying the load of the next page.

The best solution is to use navigator.sendBeacon: https://developer.mozilla.org/en-US/docs/Web/API/Navigator/sendBeacon

window.addEventListener("unload", logData, false);

function logData() {
  navigator.sendBeacon("/log", analyticsData);
}

This method is intended for analytics and diagnostics code to send data to a server.

A problem with sending analytics is that a site often wants to send analytics when the user has finished with a page: for example, when the user navigates to another page. In this situation the browser may be about to unload the page, and in that case the browser may choose not to send asynchronous XMLHttpRequest requests.

In the past, web pages have tried to delay page unload long enough to send data. To do this they have used workarounds such as:

  • Submitting the data with a blocking synchronous XMLHttpRequest call.
  • Creating an element and setting its src. Most user agents will delay the unload to load the image.
  • Creating a no-op loop for several seconds.

All these methods block unloading the document, which slows down navigation to the next page. There's nothing the next page can do to avoid this, so the new page seems slow, even though it's the fault of the previous page.

With the sendBeacon() method, the data is transmitted asynchronously when the user agent has an opportunity to do so, without delaying unload or the next navigation. This means:

  • The data is sent reliably
  • It's sent asynchronously
  • It doesn't impact the loading of the next page
Ventricular answered 25/6, 2018 at 11:31 Comment(6)
This is EXACTLY the solution I've been looking for for ages. +1, and I'd upvote again if I could!Mahogany
Finally found a solution after looking for several days. This very helpful @mofojed. Thanks a lot.Run
I like sendBeacon. The only gotcha to be noted is that is using POST and can not be changed.Savanna
sendBeacon is now called asynchronously. So next tab performance is not affected. you may want to edit the answerController
@Controller It was already asynchronous, the block quote snippet was from the MDN page explaining other methods that were wrong/synchronous. They've updated the language on the MDN page though so I've updated this answer to include that.Ventricular
hello this solution working or notCaputo
P
4

It is very tricky because the browser will not wait untill the response comes so the ajax request might get aborted.

You can try something like this in beforeunload event.

$(window).bind("beforeunload", function() {
    $.ajax({
        async: false,//This will make sure the browser waits until request completes
        url: "${contextPath}/notify?direction=logout"
    });
});
Parabolic answered 10/2, 2012 at 22:22 Comment(1)
That's unreliable and while you can "try" that and it may work, it should never be used on a production environment.Wilder
W
1

Even if this were possible, I still wouldn't recommend it. In the event you manage to get this working it wont work in all browsers and I'd still advise against it entirely.

If you're that desperate to know when a user leaves your domain, use polling or websockets with a fallback.

You could also give cookies a short timeout and use intervals to update them periodically while on the site, tricks like that would even work.

Also, it "starts" working while traced, because the event is fired before the next page even begins loading. It's been a while, but last time I played with these events, but some browsers may execute code for a period of time while the next page loads.

Wilder answered 10/2, 2012 at 22:45 Comment(1)
Not 100% reliability is OK for my task, because I have backup solutions like you said. The problem with periodical polling is that is does not work fast. So I need a fast solution which works with some of browsers.Tequila
K
0

You're out of luck, it would be impossible for a user to quit a page if the JavaScript executed on page unload were blocking.

Imagine all the spam.

On some browsers, the unload event will fire, but a race condition will occur between your script and cleanup of the page.

Thanks

Kutz answered 10/2, 2012 at 22:21 Comment(0)
A
-1

I don't want to say this as a comment because , I was working on this scenario long time back. I would save all information to the server when an end-user accidentally or intentionally closes the browser. I would tell you.. It was working great.,

I said working great right ? Well it was only with Firefox and IE. It failed in many other browsers (like Opera, Safari).

So my kind advice is not to depend on these functions , as they are only browser-specific.

Adorne answered 10/2, 2012 at 22:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.