Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Execute server API call on beforeunload/ Limitations on page unload?

The below code is used to work in chrome and suddenly stopped due to chrome recent change "Disallow sync XHR in page dismissal". The recent update on Crome early April 2019, I think Chrome 73.0.3683.103 stopped this feature and they have suggested sendBeacon or fetch keepalive. I will post what I was tried so this might help someone else.

https://www.chromestatus.com/feature/4664843055398912

$(window).on('beforeunload', function (e) {
     //ajax call used work in Chrome 
}

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

I know there are several related posts related to the same situation, but still couldn't find a solution. I tried several ways to make a server call.

Step 1:

$(window).on('beforeunload', function (e) {
 if (navigator.sendBeacon) {
    navigator.sendBeacon('url', 'data');
 } else {
    $.ajax({
        type: 'POST',
        url: 'url',
        data: null,
        contentType: 'application/json;',
        async: false
    });
 }
}

This did not work due to content type - application-json

Step 2:

$(window).on('beforeunload', function (e) {
 var data = { ajax_data: 22 };
 var blob = new Blob([JSON.stringify(data)], {type : 'application/json'});
 navigator.sendBeacon('url', blob);
}

This code did not work due to sendBeacon only support these content-types

  • multipart/form-data
  • application/x-www-form-urlencoded
  • text/plain

Step 3:

 $(window).on('beforeunload', function (e) {
  if (fetch) {
    fetch(url, {
        method: "POST", headers: { "Content-Type": "application/json" } 
    }).then(function (response) {
        console.log(response.statusText);
    }).then(function (response) {
        console.log(response.statusText);
    });
    return false;
 } else {
    $.ajax({
        type: 'POST',
        url: 'url',
        data: null,
        contentType: 'application/json;',
        async: false
    });
 }
}

This code works!. But only when you click on a link on the page or click on the Signout button. I need to work on this server method on when the user leaves the page on clicking on a link, signout, tab close and browser close.

Step 4:

$(window).on('beforeunload', function (e) {
     e.stopPropagation();
     e.preventDefault();
     fetch('url', { method: 'POST', headers: { 'Content-Type': 'application/json' } }); 
}

This will show a popup "Leave site?", I don't want to the user to show any popup.

Step 5:

$(window).on('beforeunload', function (e) {
      setTimeout(function ()
      {
           fetch('url', { method: 'POST', headers: { 'Content-Type': 'application/json' } });        
      }, 3000);
      return false;
}

Also same as step 4, shows the "Leave site popup."

Now I'm running out of options and could not found a solution yet. Any help appreciated. I need a server call before page unloads by clicking on a link, logout, tab close, browser close. The above code will work if you put a breakpoint, which means it needs some time delay to send the server call before page unload. I don't mind putting a timeout if the user does not see any popup like "Leave site?"

like image 550
Kapila Perera Avatar asked Sep 13 '25 16:09

Kapila Perera


1 Answers

This is an old question, but you need to use fetch with the keepalive flag set to true in the beforeunload event:

fetch(url, {
   method: "POST",
   keepalive: true, 
   headers: { 
      "Content-Type": "application/json" 
   }
});

sendBeacon does not behave the way documentation claims it does. In my testing, it did not respect the MIME type of a Blob in the request body, even if the Blob was a "supported" MIME type.

Use fetch instead. It gives you more control over the request headers, while guaranteeing that your request will be issued like sendBeacon supposedly does.

You might also need to bind the beforeunload event in the body of the page. A jQuery binding might not work for beforeunload.

like image 119
mr_schmiggles Avatar answered Sep 16 '25 07:09

mr_schmiggles