javascript - 在卸载前执行服务器 API 调用/页面卸载的限制?

标签 javascript jquery

下面的代码用于在 Chrome 中工作,但由于 chrome 最近的更改“在页面关闭中不允许同步 XHR”而突然停止。 2019 年 4 月上旬的 Crome 最近更新,我认为 Chrome 73.0.3683.103 停止了此功能,他们建议使用 sendBeacon 或 fetch keepalive。我将发布我尝试过的内容,以便这可能对其他人有所帮助。

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

我知道有几个相关帖子涉及相同的情况,但仍然找不到解决方案。我尝试了多种方法来进行服务器调用。

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

由于内容类型 - application-json,这不起作用

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

此代码不起作用,因为 sendBeacon 仅支持这些内容类型

  • 多部分/表单数据
  • application/x-www-form-urlencoded
  • 文本/纯文本

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

这段代码有效!但仅当您单击页面上的链接或单击“注销”按钮时。当用户通过单击链接、注销、选项卡关闭和浏览器关闭离开页面时,我需要处理此服务器方法。

第 4 步:

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

这将显示一个弹出窗口“离开站点?”,我不希望用户显示任何弹出窗口。

第 5 步:

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

也与步骤 4 相同,显示“离开站点弹出窗口”。

现在我已经没有选择了,还找不到解决方案。任何帮助表示赞赏。我需要在页面卸载之前通过单击链接、注销、选项卡关闭、浏览器关闭进行服务器调用。如果放置断点,上面的代码将起作用,这意味着在页面卸载之前需要一些时间延迟才能发送服务器调用。如果用户没有看到任何弹出窗口(例如“离开网站?”),我不介意设置超时

最佳答案

这是一个老问题,但您需要在 beforeunload 事件中将 keepalive 标志设置为 true 来使用 fetch:

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

sendBeacon 的行为与文档声称的不同。在我的测试中,它不考虑请求正文中 Blob 的 MIME 类型,即使 Blob 是“受支持的”MIME 类型。

改用fetch。它使您可以更好地控制请求 header ,同时保证您的请求将像 sendBeacon 那样发出。

您可能还需要在页面正文中绑定(bind) beforeunload 事件。 jQuery 绑定(bind)可能不适用于 beforeunload。

关于javascript - 在卸载前执行服务器 API 调用/页面卸载的限制?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60530716/

相关文章:

javascript - 删除 object.property 不适用于 Mongoose 创建的对象

jquery - 如何仅在批量 getJSON 指令完成时触发某些操作?

javascript - 使用jquery在循环中分页上一个和下一个

jquery - 如何使用 jQuery 对点击链接的边框进行动画处理?

javascript - 显示模态时执行功能

javascript - 如何使用 jQuery Cookie 插件设置/读取 cookie 的值

javascript - React Typescript Log in不发送请求,但重新渲染主要组件

javascript - 使用 location.reload() 后滚动到特定的 div

javascript - 使用 jquery 操作 css "content: attr(data-tooltip)"

jquery - 获取 jQuery 中所有选定元素的列表