3

I have a dashboard where users can toggle some input values in order to configure the appearance of the page.

I want to store those changes in a DB table, so when user comes back, the dashboard appears according to the specific user configuration retrieved from the DB.

I know how to send those values to DB and how to retrieve them

I don't want to make ajax calls every time the user changes a configuration.

Instead, I think this senario would be better:

  1. Page load (retrieve DB configuration if exist)
  2. User toggles the configuration ui items (e.g. checkboxes, select etc) and the appropriate client side changes take place (some divs get hidden, some others are shown etc and the config input values are stored to a hidden field), but no ajax call takes place.
  3. When user clicks a link to another page, the configuration input values (which have been stored to the hidden field) are sent to the DB via ajax call.

MY QUESTION

One solution(?) would be the use of onbeforeunload event like this:

window.onbeforeunload = function(e) {
   // Perform the ajax call
   return 'Do you want to save the configuration changes?';
};  

But, if the user's browser prevent popups, the function will not get executed?

Is there a way to perform an ajax call on onbeforeunload event, without calling a dialog box?

kapantzak
  • 11,610
  • 4
  • 39
  • 61
  • I think `NO` you can't assume that users want to close `Window/Tab ` of your tab. Even `onbeforeunload` also not work if User Cancel your pop-up . – Anant Dabhi Apr 24 '15 at 12:12
  • I don't know that it would 100% work but you can try trigger ajax to mouseleave function on body. And for the links add a event listener to anchor tag. – Janaka Dombawela Apr 24 '15 at 12:17
  • You could use WebSockets. Even if you are supporting older IE's I am sure there are shims available. – trysis Apr 24 '15 at 13:07

3 Answers3

6

No. During unload, the browser will kill all pending requests. So the AJAX might or might not arrive at the server. You also can't do it inside the handler of the beforeunload event because the first A in AJAX means: Asynchronous -> Just put the request on the stack and eventually execute it. So the request will be looked at only after the handler returns. But very soon after that, the browser will kill anything related to the page.

The solution is to always send updates to the server while the users makes changes. Put those into a special "temporary" table from which you can restore the state later.

You could also use something like localStorage in the browser but then, the data wouldn't move with the user. For example if they were working on an tablet and that broke or had a power loss, they could move to their PC to continue where they left off.

Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820
0

You can't guarantee that an Ajax call will complete in this way, see Aaron's response. My suggestion would be to use something like localStorage to read / write the user's settings instead.

If you need a user's appearance to persist across multiple devices, add a periodic request to read / write the recent updates from localStorage to the central DB.

Graham
  • 6,484
  • 2
  • 35
  • 39
0

Try using Navigator.sendBeacon on the visibilitychange event.

document.addEventListener("visibilitychange", () => {
  if (document.visibilityState === "hidden") {
    navigator.sendBeacon("/ajaxUrl");
  }
});

Regarding Navigator.sendBeacon(), MDN details that when leaving a page,

the browser may choose not to send asynchronous XMLHttpRequest requests. 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

Regarding the visibilitychange event, MDN recommends:

Web sites often want to send analytics or diagnostics to the server when the user has finished with the page. The most reliable way to do this is to send the data on the visibilitychange event

Elijah Mock
  • 587
  • 8
  • 21