9

I am trying to send some requests to the database when the window is unloaded (i.e. when you refresh the page). For some reason, only on Safari, the client side code gets executed, but the request to the server never goes through. When I step through the code manually in the debugger, the server does get the request and processes it fine.

Anyone know why this is happening?

window.onbeforeunload = function() {
  console.log("inside on before unload");
  var requestParam = new a.ListRequest();
  requestParam.setAction('set_delete');
  
  var callback = function(isSuccess, response) {
    if (isSuccess) {
      //do something
    } else {
      // do something else
    }
  };
  
  // Sends request to server
  a.Fetch.list(requestParam, callback);
  
}
petranaya
  • 769
  • 1
  • 6
  • 23
  • Without seeing your code, the only guess I could give is.. you have a bug in your code. – Lil Devil Dec 11 '15 at 20:49
  • It works on Chrome and Firefox though. I'll add some sample code too – petranaya Dec 11 '15 at 20:50
  • What do you send to the server? Also why do you want this sent onbeforereload? – Pablo Jomer Dec 16 '15 at 09:40
  • I'm sending a request to the server to update the database and I want this to happen before the page unloads. The server then sends a response back saying failed or succeeded. (this is all asynchronous) – petranaya Dec 16 '15 at 16:30

4 Answers4

5

Likely the request that happens in the Fetch call is asynchronous and Safari is not waiting for it to finish before moving on to the next page/closing the tab. If you can make the call synchronous it should work. Keep in mind that synchronous calls are generally discouraged and deprecated in some tools.

This answer related to Jquery has a good explanation of synchronous calls: https://stackoverflow.com/a/11755262/1341437

Community
  • 1
  • 1
craigts
  • 2,857
  • 1
  • 25
  • 25
2

You can use Beacon API (FF, Chrome, Opera):

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

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

User agents will typically ignore asynchronous XMLHttpRequests made in an unload handler. To solve this problem, analytics and diagnostics code will typically make a synchronous XMLHttpRequest in an unload or beforeunload handler to submit the data. The synchronous XMLHttpRequest forces the User Agent to delay unloading the document, and makes the next navigation appear to be slower. There is nothing the next page can do to avoid this perception of poor page load performance.

Using the sendBeacon() method, the data will be transmitted asynchronously to the web server when the User Agent has had an opportunity to do so, without delaying the unload or affecting the performance of the next navigation.

Alex
  • 11,115
  • 12
  • 51
  • 64
0

You can do it with jQuery.ajax by set the async property to false async:false

window.onbeforeunload = function() {
    $.ajax({
        // Query to server
        async:false,
        method: "GET",
        url: "your.page",
        data: { param1 : "value1" }
    }).done(function(jqXHR, textStatus) {
        // Verify good data
        // Do stuff
        alert( "Request done: " + textStatus );
    }).fail(function( jqXHR, textStatus ) {
        alert( "Request failed: " + textStatus );
    });
}
Pedram
  • 828
  • 9
  • 24
0

As @craigts said, the browser is gone before the ajax call can be returned. You might get a few more seconds on that page.

window.onbeforeunload = function(e) {
  return 'Dialog text here.';
};

However, your users will find this annoying.

2nd option, find another event instead of waiting for the page unload. Capture your data continuously. Capture it onChange. Will the user be using a link to continue? If so you can hijack the link with cancelEvent() and then continue after the ajax has returned.

Rob Y
  • 214
  • 1
  • 9
  • I debated whether to provide an alternate solution like your second option since that is the main way I've solved this problem in sites I've worked on. – craigts Dec 21 '15 at 17:53