【问题标题】:How to send AJAX request when user leaves (closes) the page?用户离开(关闭)页面时如何发送 AJAX 请求?
【发布时间】:2013-09-17 01:10:52
【问题描述】:

情况

嗨, 我正在制作一个数据库驱动的游戏,其中有一个问题,如果用户找到正确的答案,他们有权更改问题(即写一个新问题)。

但这有一个重要的问题,我认为它被称为竞争条件。问题是这样的:

  • 用户 1 找到答案
  • 提示用户 1 输入新问题
  • 在用户 1 提交新问题之前,用户 2 也找到了新答案
  • 现在只能靠运气了,谁来提交新问题。如果用户 2 在用户 1 之后提交问题,则用户 2 的问题会覆盖用户 1 的问题。

现在,我已通过使用某种信号量并保留其timestamp 来解决此问题。总结它的工作原理是这样的:

  • 用户 1 找到答案
  • 信号量被保存到数据库中,如['user_ip' = 'x.x' , 'time'='y.y' , 'locked'='true']
  • 信号量在 t 秒后过期
  • 只有在信号量过期时才会接受新问题。

因此,当提交新问题时,只有当信号量未锁定并且当前时间比信号量的日期大t (15) 秒时,应用程序才会接受它。

但这也有问题,提示用户2

“你已经找到了答案,但有人在你之前找到了它。你可以 如果他们没有在 15 内提交新问题,请更改问题 秒。”

所以新的获胜者必须等待 15 秒,这可能是不必要的。

因此,

我想做什么

我想用秒表(计时器)提示“获胜者”一个表格。当它达到零时,它会解锁信号量,以便新的获胜者可以提交他们的问题。

但是这个方案会有这个问题:

如果获胜者在计时器归零之前关闭页面,则 AJAX 请求将永远不会完成,信号量将被无限期锁定。

所以如果用户关闭页面,我必须确保我已经调用了userLeave(); 函数。

Google 建议使用 onbeforeunload 和 onunload,但人们也抱怨这些功能不起作用。那么,如果用户(获胜者)离开页面,是否有 100% 确定发送此 AJAX 调用的方法?

【问题讨论】:

  • Ajax 是异步的,因此是非阻塞的;页面不会等到它完成才关闭。
  • 如你所想,如果页面关闭,代码将不再运行任何代码或执行请求,所有当前请求都将被取消。唯一可靠的方法是保持连接打开并尝试检测用户何时断开连接,或执行定期 ping,或两者兼而有之。
  • 是的,我知道这一点。但是强迫用户等待(比如“你确定要退出吗?”提示)或嵌入和隐藏的 swf 文件,无论如何,我想相信有一个解决方案:)
  • 您的解决方案最有可能使用 Node.JS。这样您就可以在客户端和服务器之间创建自己的持久套接字连接。如果套接字已关闭,您可以在服务器端执行 ajax 调用之前需要处理的任何操作
  • @CengizFrostclaw 这种方法不仅烦人而且不能保证。我相信可以禁用此消息,并且在任何情况下,如果用户只是失去 Internet 连接,您将无法检测到任何东西。

标签: javascript php jquery ajax forms


【解决方案1】:

如果用户(获胜者)离开页面,是否有 100% 确定发送此 AJAX 调用的方法?

您可以永远 100% 依赖客户做任何事情。想想网络连接丢失、浏览器崩溃、不可用的功能(从不兼容 HTML5 的浏览器到禁用的 javascript)、脚本错误、以意想不到的方式调用(或不调用)您的 API 的错误配置代理或黑客故意这样做......

您对客户的唯一期望是他什么都不做 - 这称为超时。

如果您希望您的信号量在某个时间过期,您必须在服务器端创建计时器。如果您愿意,您还可以在客户端发出信号表示他不会提交答案(以任何方式)时立即中止计时器并过期。如果您想尝试关闭页面,可以使用来自unload 事件的同步 (A)JAX。

顺便说一句:虽然我不了解你的游戏,但如果你只是接受这两个新问题会更容易,可能更舒服:-)

【讨论】:

  • hehe:) 但游戏本身是“一个问题,知道者改变它”,所以这不是一个选项。你是对的,免费主机的最佳选择是在服务器端处理时间。谢谢!
猜你喜欢
  • 2017-04-24
  • 2016-05-11
  • 2017-09-24
  • 1970-01-01
  • 1970-01-01
  • 2010-12-11
  • 2013-05-07
  • 1970-01-01
  • 2012-05-03
相关资源
最近更新 更多