3

Scenario: I am creating an event registration module in which a user would choose a date from a calendar for booking, fill some input fields and pay up to book the date. One of the requirements is that, there can be only one booking per date. This arises a case where two people want to book the same date on the same time. So, we need to show the user who came later to book the date a message that a booking is already in progress for that specific date. Please check back later.

For this to achieve, I am creating a temporary entry in my DB whenever a user chooses a date. Against that entry, I can show the message to the other user who came later.

Logically, that entry has to be deleted if the first user:

  1. selects some other date.
  2. closes his browser or navigate away from the page

So that it would be available for the second user who wants to book for the same date.

The Problem: I am able to delete the entry once a user changes his selected date. I am not able to achieve the second one. I wrote a function that will delete the row and calling that function onbeforeunload jQuery event. Apparently, that function is not working with jQuery.

window.onbeforeunload = function(){
  deleteTempEntry(); //This sends an ajax call to delete the entry. Not working.

  alert("The second alert"); // even this alert doesn't work.

  // I actually intend to use confirm box to make sure to not to delete the entry if the user does not leave the page.
  confirm("Your current progress will be removed. Are you sure?"); 

  //Calling this return function shows the warning message but none of the other code works.
  //return 'Are you sure you want to leave?';
};

I tried, bind/on/pure JS but none of those seem to work.

As explained here, there isn't really much I can do with onbeforeunload/unload events because of the security reasons. Any workaround for this?

Thanks.

Community
  • 1
  • 1
Awais Umar
  • 2,027
  • 3
  • 27
  • 46
  • how about a opening a new window ? then show your messages there, and the unload on the popup should trigger the `deleteTempEntry()` –  Apr 06 '17 at 07:30
  • So, there is not much you can do on the front-end when the user is closing the tab/browser. So you will have to maintain a timeout function on the backend, so that it deletes the incomplete registration. – MegaMind Apr 06 '17 at 07:33

4 Answers4

11

I needed something like that. But unfortunately calling the backend in onBeforenUnload is not reliable. Most AJAX calls will not reach the backend (some may); The only guaranteed call is with navigator.sendBeacon(url, data). It sends POST request even the browser is closed.

  • Further explanation on this can be found at https://usefulangle.com/post/62/javascript-send-data-to-server-on-page-exit-reload-redirect – Peter Kerr Jul 06 '20 at 11:57
3

You can post data with async: false like this:

$(window).unload(function () {
            $.ajax({
                type: 'POST',
                async: false,
                url: 'your url',
                data: {  }
            });
        });
Majid Parvin
  • 4,499
  • 5
  • 29
  • 47
  • synchronous request will cause the browser to become un-responsive until the request is complete. – Majid Parvin Apr 06 '17 at 10:03
  • 1
    It is a syncrhonous call that is being made, so it blocks further code execution untill the request has finished. – Jesse Schokker Apr 06 '17 at 10:04
  • 1
    you're right but you are leaving the page. don't you? it doesn't matter. – Majid Parvin Apr 06 '17 at 10:06
  • @MajidParvin, I wasn't able to resolve the issue using the onbeforeunload technique. I have studied further and there is very limited functionality that you can do with unbeforeunload. Infact, it is merely a string that you can return and in the latest version of the browser, they'll tend to ignore even that. So, I'd rather shift to cron job approach. Thank you for your time. – Awais Umar Apr 08 '17 at 09:06
  • check my answer bellow – Vladimir Demirev Jun 05 '20 at 23:17
  • 2
    @VladimirDemirev seems to be correct, the async: false will not work in newer versions of browsers. see https://usefulangle.com/post/62/javascript-send-data-to-server-on-page-exit-reload-redirect – Peter Kerr Jul 06 '20 at 11:56
2

Try console.log and return in your onbeforeunload method. maybe user leaves the page before your ajax goes through.

See: https://developer.mozilla.org/en-US/docs/Web/API/WindowEventHandlers/onbeforeunload

Since 25 May 2011, the HTML5 specification states that calls to

  • window.alert()
  • window.confirm()
  • window.prompt()

commands may be ignored during this event.

ClickThisNick
  • 5,110
  • 9
  • 44
  • 69
Sahal Tariq
  • 198
  • 1
  • 9
  • I understand that. That's why I planned to use confirm method so to make sure the ajax request goes. But confirm(), alertI(), they don't work. – Awais Umar Apr 06 '17 at 09:03
  • @Symbolwdd - im not sure about this but, try to send an ajax in the beforeunload function and return null to it from response of ajax. again, not sure, just trying to give an idea. since the beforeunload prompt triggers when this method is returned a value. – Sahal Tariq Apr 06 '17 at 09:14
  • Thank you for the documentation. Looks like onbeforeunload is not on the table anymore. I'll have to shift to cron job in that case. – Awais Umar Apr 08 '17 at 09:03
1

You can make the client send out a "heartbeat" every 30 seconds or so to the server, and update a record in the database with a timestamp of the last sent heartbeat along with a reference to the booking date. Then run a cronjob which runs every minute or so, which checks all of those records, and if one of them is over let's say over 120 seconds old, then delete the record.

Jesse Schokker
  • 896
  • 7
  • 19
  • It makes sense. But we actually have given a user, 20min timespan to complete the form and do the transaction. After that, the session will expire. Combined with that requirement, applying the approach you have suggested would cause problem unfortunately. – Awais Umar Apr 06 '17 at 09:04
  • You can extend the timeout. This probaly is the only solution that is reliable, which you need as it is a important part of your system. – Jesse Schokker Apr 06 '17 at 10:02