'onbeforeunload'两次射击

时间:2012-01-03 11:10:52

标签: javascript ajax jquery javascript-events onbeforeunload

我想在用户离开页面或关闭窗口时发送ajax请求 这是我的代码:

<script type="text/javascript">
    function sendajax(){
        $.ajax({
          url: "someurl",
          data: mydata,
          async : false
        });   
    }
</script>
    <script type="text/javascript">
     window.onbeforeunload=function(){sendajax();};
</script>   

事件发生时,事件会触发两次 为什么会发生?
我知道我可以通过添加变量var ajaxSent=true;来阻止它,但可能有更简洁的方法吗?

UPD:
我用一些其他代码(不发送ajax)替换了sendajax函数内容,并发现ajax不是导致问题的那个。它仍然会进入该功能两次。

5 个答案:

答案 0 :(得分:5)

根据您的编辑和评论中的代码,看起来它可能只是由您点击离开页面的断开链接引起的。

给出以下代码:

<script>
    function doSomething() { console.log('onbeforeunload fired'); }
    window.onbeforeunload = doSomething;
</script>
<a href="garbage">link A</a>
<a href="http://google.com">link B</a>

如果我点击链接A,我会收到两个控制台日志条目,如果我点击链接B我只会得到一个。

看起来可能是浏览器如何处理其内部“未找到此网页”页面的怪癖,导致您的页面在显示消息之前被刷新并再次关闭,让您两次出现onbeforeunload事件。

答案 1 :(得分:1)

我遇到了同样的问题,花了一段时间才了解并解决,并分享了案例详细信息:

我们的模板中有一个自定义JS,用于操作菜单。 仅在单击菜单链接时,而不是在其他链接上,并且仅在IE / EDGE中,这导致卸载触发两次。

我们最终停止了在这些链接上的传播,问题得以解决。

$('.SELECTOR a[href^="http://"]').on('click', function(e){
    e.stopPropagation();
});

这是您应用程序中的一个特定错误,因此您不会在Google上找到太多信息。

答案 2 :(得分:0)

您可以尝试以下代码:

<script type="text/javascript"><br>
     window.onbeforeunload=function sendajax(){<br>
        $.ajax({<br>
          url: "someurl",<br>
          data: mydata,<br>
          async : false<br>
        });<br>
};<br>
</script>

或者您可以在某个地方定义sendajax() {},并使用它onbeforeunload = "sendajax()"而不是onbeforeunload = "function () { sendajax() }"

答案 3 :(得分:0)

取消卸载之前

我知道这篇文章已经很老了,但是从Chrome Pagelifecycle API文档来看,浏览器有时可以部分卸载页面以节省资源。 this answer的beforeUnload不可靠,无法确保该页面已关闭。屏幕锁定时,这尤其会在android设备上发生。

我发现有人写了一个jsfiddle,您可以测试https://developers.google.com/web/updates/2018/07/page-lifecycle-api。在Chrome android上将屏幕锁定5至10分钟,您会看到在甚至不关闭标签页的情况下触发了beforeUnload。

$(document).ready(function() {
    window.addEventListener('beforeunload', showLoader);
});

var showLoader = function() {
    $('#loader').show();
};

答案 4 :(得分:0)

同意 AlonMichaeli 的观点。 在我的应用程序中,有一个包含在 div 中的锚标记和几个跨度。当在脏页面上单击锚点时,会出现几个“离开站点”通知。 如果单击 menuItem(div 或 spans)的任何其他部分,它工作正常。 因此,在自定义 javascript 方法中,我仅在单击锚标记时添加了停止传播和 preventDefault。不知何故,在这种情况下, preventDefault 是必要的。

function menuItemClicked(event: JQueryEventObject) {
  var item = $(event.target);
  if (item.is(".anchor-item")) { 
    event.stopPropagation();
    event.preventDefault();
  }
  href = item.closest(".anchor-item").attr("href");
  if (!event.ctrlKey && href) {
    window.location.href = href;
  }
}