最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Safari does not run callback function on refreshonbeforeunload on server side (calls client side code) - Stack Over

programmeradmin0浏览0评论

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);
  
}

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);
  
}

Share Improve this question edited Dec 11, 2015 at 20:56 petranaya asked Dec 11, 2015 at 20:36 petranayapetranaya 7791 gold badge6 silver badges23 bronze badges 4
  • Without seeing your code, the only guess I could give is.. you have a bug in your code. – Lil Devil Commented Dec 11, 2015 at 20:49
  • It works on Chrome and Firefox though. I'll add some sample code too – petranaya Commented Dec 11, 2015 at 20:50
  • What do you send to the server? Also why do you want this sent onbeforereload? – Pablo Jomer Commented Dec 16, 2015 at 9: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 Commented Dec 16, 2015 at 16:30
Add a ment  | 

4 Answers 4

Reset to default 5 +50

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./a/11755262/1341437

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.

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 );
    });
}

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.

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论
ok 不同模板 switch ($forum['model']) { /*case '0': include _include(APP_PATH . 'view/htm/read.htm'); break;*/ default: include _include(theme_load('read', $fid)); break; } } break; case '10': // 主题外链 / thread external link http_location(htmlspecialchars_decode(trim($thread['description']))); break; case '11': // 单页 / single page $attachlist = array(); $imagelist = array(); $thread['filelist'] = array(); $threadlist = NULL; $thread['files'] > 0 and list($attachlist, $imagelist, $thread['filelist']) = well_attach_find_by_tid($tid); $data = data_read_cache($tid); empty($data) and message(-1, lang('data_malformation')); $tidlist = $forum['threads'] ? page_find_by_fid($fid, $page, $pagesize) : NULL; if ($tidlist) { $tidarr = arrlist_values($tidlist, 'tid'); $threadlist = well_thread_find($tidarr, $pagesize); // 按之前tidlist排序 $threadlist = array2_sort_key($threadlist, $tidlist, 'tid'); } $allowpost = forum_access_user($fid, $gid, 'allowpost'); $allowupdate = forum_access_mod($fid, $gid, 'allowupdate'); $allowdelete = forum_access_mod($fid, $gid, 'allowdelete'); $access = array('allowpost' => $allowpost, 'allowupdate' => $allowupdate, 'allowdelete' => $allowdelete); $header['title'] = $thread['subject']; $header['mobile_link'] = $thread['url']; $header['keywords'] = $thread['keyword'] ? $thread['keyword'] : $thread['subject']; $header['description'] = $thread['description'] ? $thread['description'] : $thread['brief']; $_SESSION['fid'] = $fid; if ($ajax) { empty($conf['api_on']) and message(0, lang('closed')); $apilist['header'] = $header; $apilist['extra'] = $extra; $apilist['access'] = $access; $apilist['thread'] = well_thread_safe_info($thread); $apilist['thread_data'] = $data; $apilist['forum'] = $forum; $apilist['imagelist'] = $imagelist; $apilist['filelist'] = $thread['filelist']; $apilist['threadlist'] = $threadlist; message(0, $apilist); } else { include _include(theme_load('single_page', $fid)); } break; default: message(-1, lang('data_malformation')); break; } ?>