Safari在服务器端的刷新/加载前不运行回调函数(调用客户端代码)

Safari does not run callback function on refresh/onbeforeunload on server side (calls client side code)

本文关键字:函数 回调 调用 客户端 代码 运行 服务器端 刷新 加载 Safari      更新时间:2023-09-26

我正试图在卸载窗口时(即刷新页面时)向数据库发送一些请求。出于某种原因,只有在Safari上,客户端代码才会被执行,但对服务器的请求永远不会通过。当我在调试器中手动遍历代码时,服务器确实会收到请求并对其进行良好处理。

有人知道为什么会发生这种事吗?

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

Fetch调用中发生的请求可能是异步的,Safari在进入下一页/关闭选项卡之前没有等待它完成。如果您可以使调用同步,它应该可以工作。请记住,在某些工具中,同步调用通常是不鼓励和不推荐使用的。

这个与Jquery相关的答案很好地解释了同步调用:https://stackoverflow.com/a/11755262/1341437

您可以使用Beacon API(FF、Chrome、Opera):

window.addEventListener('unload', logData, false);
function logData() {
    navigator.sendBeacon("/log", analyticsData);
}

用户代理通常会忽略卸载处理程序中生成的异步XMLHttpRequests。为了解决这个问题,分析和诊断代码通常会在unloadbeforeunload处理程序中生成同步XMLHttpRequest来提交数据。同步XMLHttpRequest迫使用户代理延迟卸载文档,并使下一次导航看起来更慢。下一页无法避免这种页面加载性能差的感觉。

使用sendBeacon()方法,当用户代理有机会将数据异步传输到web服务器时,不会延迟卸载或影响下一次导航的性能。

您可以使用jQuery.ajax将async属性设置为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 );
    });
}

正如@craigts所说,在返回ajax调用之前,浏览器已经关闭。你可能会在那一页上多停留几秒钟。

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

然而,您的用户会觉得这很烦人。

第二个选项,查找另一个事件,而不是等待页面卸载。持续捕获您的数据。在Change上捕捉它。用户会使用链接继续吗?如果是这样,您可以使用cancelEvent()劫持链接,然后在ajax返回后继续。