【问题标题】:Can the unload Event be Used to Reliably fire ajax Request?可以使用 unload 事件可靠地触发 ajax 请求吗?
【发布时间】:2011-04-04 19:11:17
【问题描述】:

我需要一种方法来监视用户编辑会话,我正在审查的解决方案之一是让我使用unload 事件发送 ajax 请求以通知服务器编辑会话结束。 (见:Monitoring User Sessions to Prevent Editing Conflict

我对@9​​87654323@ 事件的(相当有限的)阅读表明附加到此处理程序的代码必须快速运行,因此通常用于清除对象以防止内存泄漏。

我的问题是,这是否可以足够可靠地用于此目的?

PS。我知道async: false 选项。

【问题讨论】:

    标签: javascript ajax events reliability


    【解决方案1】:

    您必须自己测试您的特定场景是否适用于您在unload 中的时间,但是发出 AJAX 请求非常快,因为 AJAX 是异步的。您只需发送请求,然后您就完成了! (不过,也许您必须清除刚刚创建的请求对象。)

    如果您想验证 AJAX 请求是否成功,那么您将不得不担心更多/使用async:false 选项(如this discussion 表示)。但是,仅仅发送是一个快速的操作,你就完成了。

    【讨论】:

    • 好吧,如果它无法到达服务器,我不会称它为可靠的,对吧? ;)
    • 没错,但我认为您的意思是可靠的,因为浏览器实际上会发送请求。
    【解决方案2】:

    我们有一个需要它的案例。这是一个需要服务器上大量内存的报告页面,因此我们希望在他们离开页面后立即释放它。我们创建了一个框架集并在那里添加了卸载处理程序。最可靠的方法是将图像的 src 设置为释放脚本。我们实际上同时使用了 unload 和 onbeforeunload 来实现跨浏览器兼容性。它在 web kit nightlies 中不起作用,但管理层对此表示满意。

    但是,这不是我建议的解决方案。我会使用心跳方法,它涉及更多的工作,但更健壮。

    您的页面应定期发送检测信号请求。每个请求都会设置页面的最后一个心跳。然后,您需要一个在服务器上运行的线程,并在上次心跳时间过长时清除内存。

    这并不能解决长时间离开页面的问题。为此,您需要对用户活动进行一些监控,并在一段时间不活动后离开该页面(确保您与用户确认)

    【讨论】:

    • 真的需要frameset,图像和释放脚本方法吗?这似乎相当骇人听闻......或者与使用两个 unload 事件相比,这是否更可靠?
    • 我们需要框架集,因为页面内正在进行导航,我们只想在离开页面集时发送“空闲内存”请求。 image/two-unload 方法是我们让它跨浏览器和操作系统最可靠地运行的方式。
    【解决方案3】:

    如果您的服务器响应速度足够快,则此方法相当可靠。不过确实要注意的事情。如果您关闭浏览器并在卸载事件时发送 AJAX 请求,则很有可能在窗口对象被销毁之前响应不会及时从服务器返回。在这种情况下(至少在 IE 中)发生的情况是,它将孤立您的连接对象,并且在连接超时发生之前不会正确终止它。如果您的服务器没有打开连接保持活动,在您关闭 2 个窗口后(同时仍然打开另一个窗口),您将用完与服务器的打开连接(对于 IE6-7,对于 IE8-6 窗口)在连接超时之前,您将无法打开您的网站。

    我之前遇到过这样的情况,我打开一个弹出窗口,在卸载时发送一个 AJAX 请求,它非常可靠,但是受到上述问题的困扰,对我来说花了很长时间追踪它并了解发生了什么。在那之后,我所做的是确保打开的窗口将具有相同的代码来调用服务器,并且在每次卸载时检查打开器并在那里运行代码(如果存在)。

    如果关闭最后一个浏览器窗口,IE 似乎会正常破坏连接,但如果另一个窗口打开,则不会。

    附:只是为了评论上面的答案,AJAX 并不是真正的异步。至少它的JS实现不是。发送请求后,您的 JS 代码仍将等待服务器的响应。它不会阻止您的代码执行,但由于服务器可能需要一段时间才能响应(或者足够长的时间让 Windows 终止 IE 窗口对象),您可能会并且很可能会遇到上述问题。

    【讨论】:

    • 有没有人在关闭异步的情况下试过这个?我猜这会阻止浏览器在请求返回之前卸载。
    • 没错。关闭异步后,浏览器将在卸载页面之前等待服务器的响应。这有助于解决 Chrome 错误,其中 Chrome 在卸载事件和异步操作时非常不可靠。这也将解决我上面描述的 IE 连接占用问题。但它将是用户可见的。
    • 值得关注带有 Navigator.sendBeacon 的新 Beacon API,它可以更好地在卸载时可靠地向我们的服务器发出异步请求:developer.mozilla.org/en-US/docs/Web/API/Navigator/sendBeacon
    • 不推荐使用同步请求,使用 async:false 调用 ajax 将来会停止工作。 developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest搜索async
    • 同步请求支持已从 Chrome 版本 82 中删除。
    【解决方案4】:

    你试过用吗

    var i = new Image(1,1); 
    i.src='http://...'
    

    只是从服务器返回一些空图像。我认为它应该是可靠的,脚本会阻塞。顺便说一句:很高兴添加时间戳以防止缓存。

    【讨论】:

    • 我发现onload事件函数中的AJAX调用不起作用,但是这个方法可以。需要注意的是,函数代码不会停止或阻止页面卸载,代码可能会在页面卸载后执行。
    【解决方案5】:

    我有一个案例,我只需要通知服务器端卸载,并不关心响应。

    如果这是你的情况,你可以 ignore_user_abort 然后你知道它会“可靠地”发生

    【讨论】:

      猜你喜欢
      • 2013-03-06
      • 1970-01-01
      • 1970-01-01
      • 2018-12-25
      • 2012-01-24
      • 1970-01-01
      • 1970-01-01
      • 2014-09-21
      • 1970-01-01
      相关资源
      最近更新 更多