JQuery在页面卸载时的Ajax请求

74

我想实现这个:

$(window).unload( function () { 

$.ajax({
    type: "POST",
    url: "http://localhost:8888/test.php?",
    data: "test",
    success: function(msg){
         alert( "Data Saved: " + msg );
    }
}); 
alert (c);
});
然而,成功提示从未显示,而且这个请求似乎甚至没有到达服务器。我做错了什么?
7个回答

83

我认为您需要使用async : false参数将请求改为同步方式,因为默认情况下它是异步的。

同步请求会在请求完成之前锁定浏览器。如果请求是异步的,页面将继续卸载。这很快,以至于请求甚至没有时间触发。


谢谢。您能解释一下为什么这个必须是同步的吗? - zigomir
2
同步请求会锁定浏览器,直到它们完成。如果请求是异步的,页面将继续卸载。这很快,以至于请求甚至没有时间触发。 - Nate B
这是否意味着,如果浏览器需要更长时间才能卸载(可能是硬盘问题),请求有时会被发送?还是永远不会发送?只是好奇。 - Farzher
11
虽然这是正确的答案,但你没有指出这种方法是“邪恶的”,这让我感到不满。在网络连接缓慢的情况下,采用这种方式会使用户的浏览器停顿。 - Mark Amery
没有产生任何影响。 - user3953989
它非常快,以至于请求甚至没有时间触发。在某些情况下,它实际上会触发事件,但不会等待响应,从而导致连接关闭。 - Juan Carlos Mendoza

22

尝试使用 async = false 调用它;

jQuery.ajax({url:"http://localhost:8888/test.php?", async:false})

我刚刚尝试了它。


18

最好的解决方案是使用navigator.sendBeacon。这是全新的功能,在新版本的浏览器中开始实现。该函数可在 Chrome 39 及 Firefox 31 以上的浏览器中使用,但目前不支持 Internet Explorer 和 Safari 浏览器。为确保您的请求在尚未支持此新功能的浏览器中得到发送,您可以使用以下解决方案:

var navigator.sendBeacon = navigator.sendBeacon || function (url, data) {
  var client = new XMLHttpRequest();
  client.open("POST", url, false); // third parameter indicates sync xhr
  client.setRequestHeader("Content-Type", "text/plain;charset=UTF-8");
  client.send(data);
};

这个函数不允许你注册一个onsuccess回调函数。


1
目前,这仍被列为实验性质的,并且“语法和行为...可能会在未来版本中发生变化”。 - Jeff Walker Code Ranger
更新:当您编写此答案时可能不太清楚,但是不应该在unloadbeforeunload事件中使用sendBeacon,因为它可能无法可靠地触发 - 应改用visibilitychange事件。有关更多信息,请参见MDN文档。 - Henry Floyd

3
HTML5规范指出,在 window.unload() 事件期间,alert()prompt() 等方法将不可用。有关更多详细信息,请参见 window.unload()。您可以使用 console.log('success'); 代替 alert() 来检查结果。

2
也许你可以尝试使用onbeforeunload事件,这样可能会更成功一些?
   $(window).bind('beforeunload', ...

2
beforeunload事件在Safari中不受支持。 - Sergey P. aka azure

0
您的函数和Ajax调用看起来很好,所以我猜测是因为在ajax调用有时间去服务器和返回之前,您的浏览器窗口关闭了。 当窗口关闭时,ajax调用可能会返回一些东西,请尝试将错误函数添加到您的ajax调用中,以查看是否是这种情况:
error: function (xhr, textStatus) {
    alert('Server error: '+ textStatus);
}

1
我并不需要它“返回”(即成功提示并非必要,仅用于调试目的)。但是,在卸载完成之前,我确实需要发出ajax请求。 - Rob

0

MDN建议在visibilitychange事件上使用navigator.sendBeacon

$(window).on("visibilitychange", (event) => {
    if (document.visibilityState === 'hidden') {
        navigator.sendBeacon("https://example.com/endpoint", yourDataToSend);
    }
});

(非jQuery版本将使用window.addEventListener("visibilitychange")。)

来自MDN

网站通常希望在用户完成页面后向服务器发送分析或诊断数据。最可靠的方法是在visibilitychange事件上发送数据。

应避免使用unloadbeforeunload事件。

这篇 Stack Overflow 的帖子 似乎对这种情况有很好的研究。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接