2

情况如下:

我有一个基于 Web 的票务应用程序,有多个用户。

可能发生的一个问题(并且确实发生在我要替换的旧版本中)是 user1 打开一张票,编辑它,然后保存它。但是在他编辑它的同时,user2 也打开并保存了勾选。user2 所做的更改将被 user1 丢失/覆盖。

为了防止这种情况,我实现了一个锁定机制,它相当简单:

  1. 在打开票证时,PHP 脚本会检查现有的锁。
  2. 如果没有找到,它会锁定并打开文档。
  3. 在 JS 中,setTimeout()一个 XmlHttpRequest 调用会在 10 分钟后解锁票证(工作无问题)。
  4. 我还设置了一个unload事件以在关闭/离开窗口/选项卡时解锁票

问题出在第 4 步:unload事件(& 它的朋友beforeunload)工作得不够好,无法可靠地实现这一点(要使这个特性有任何严肃的意义,它必须是可靠的),许多浏览器并不总是触发它当我希望它被解雇时(比如按下后退按钮、按 F5、关闭选项卡等。这因浏览器而异)

我能想出的唯一选择是使用setTimeout()XmlHttpRequest()调用 php 脚本来告诉它页面仍然打开。如果这个“心跳”监视器失败,我们假设用户离开票证并解锁文档。

这对我来说似乎非常低效,并且很快就会导致对服务器的许多请求,甚至只有几个用户。

有人对如何处理这个问题有更好的想法吗?

它需要在 IE8+ 和其他现代浏览器(理想情况下,Firefox、Webkit、Opera)中工作。我不关心 IE6/IE7,我们的组织不使用这些)。

4

3 回答 3

1

通过 XHR 使用心跳 ping 是可行的方法。根据用例,您可能还希望在用户停止输入字段而不是每 x 秒后发送它们 - 这将确保页面保持打开但不活动不会保持锁定状态。

如果您在用户停止输入后发送这些 XHR,请使用其中一个keydown/up/press事件和一个去抖动/节流脚本仅在用户停止输入时发送请求,例如 5 秒和每 x 秒一个(如果用户可能会长时间打字)。

于 2011-09-23T12:57:46.920 回答
1

也许这不是最好的解决方案,但值得研究一下:websockets
您可以在页面加载时与服务器建立连接,当连接失败(即客户端不响应 ping)时,您可以解锁票证。
使用socket.io 之类的东西可以确保您即使在 ie8 上也可以使用此过程。

  • 主要优点是您不必每n秒发送一次请求,而是服务器每n秒向您发送一次 ping ,您不必关心unload/beforeunload事件。如果客户端没有响应 ping,则解锁票证。
  • 主要缺点是你需要一个服务器来处理你所有的 websocket 连接,这几乎可以用任何服务器端语言来完成,但它可能比简单的 web 服务更难(在 xhr 轮询的情况下)
于 2011-09-23T13:22:44.193 回答
0

实现 ajax 心跳或卸载处理程序来自动解锁文档是很棘手的。

您的问题是,即使您在所有目标浏览器中都支持 beforeunload,如果浏览器崩溃或用户睡着了,它仍然可能不会被调用。

Look at how webdav works. You explicitly aquire a lock before you start edit, then you save and release the lock explicitly. Other users can see who has acquired a lock and admins can release locks that has been left behind by accident.

于 2011-09-23T14:37:20.440 回答