需要一个设计模式来处理在提交 HTML 表单之前未完成的 AJAX 请求
我已经完成了几个遵循类似模式的表单:
两个相互依赖的表单字段,比如说“街道地址”和“位置”(经度/纬度)。
当用户填写一个字段时,另一字段会通过 ajax 调用进行更新。
(例如,如果用户填写街道地址,则向地理编码 API 发出请求,并将结果放入位置字段中;如果用户填写位置(例如,通过地图 UI),则向地理编码 API 发出请求反向地理编码 API 并将结果放入地址字段中。 到目前为止没问题,这些很容易连接到模糊和/或焦点更改事件。)
如果在 ajax 调用完成之前提交表单,则会出现问题。在这种情况下,一个字段将具有正确的值,而另一个字段将是陈旧的。服务器上的处理程序需要检测到这种情况已经发生并更新过时的值。我们不能只检查默认值,因为用户可能多次更改这两个字段。
我想到了两种可能的解决方案,但我不太喜欢其中任何一种。我很乐意接受其他建议。
解决方案1.使用隐藏字段作为标志来指示新鲜度:默认将值设置为0,在发送ajax请求之前将其重置为0,并在响应返回时将其设置为1。在服务器端,检查这些字段并重新计算新鲜度标志设置为 0 的任何字段。这里仍然存在潜在的竞争条件,但窗口已大大缩小。我已经使用了这种技术并且它有效(例如http://fixcity.org/racks/new/)。但这很烦人,因为它在客户端和服务器上都需要更多代码,并且是另一个可能的错误来源。
解决方案 2. 使用同步 AJAX 调用(“SJAX”?)。没有吸引力,因为这里的 AJAX 只是一种 UI 便利,它对于应用程序的工作并不是绝对必要的,所以我不想让事情感觉很慢 - 然后它就变成了 UI *方便 *。
解决方案 3。 始终进行服务器端后处理。如果它很昂贵,请使用缓存来使其更便宜 - 例如。如果该值不是过时的,则意味着客户端刚刚通过 AJAX 发出了相同的请求,因此我们应该在 AJAX 处理程序期间根据需要填充缓存。 目前,这个似乎对我最有吸引力,尽管它有两个局限性: 它不能用于不安全和幂等的事物 - 例如。 AJAX 请求是否正在执行 POST;它甚至不能用于这个例子,因为我们有两个相互依赖的字段,并且无法知道哪个是正确的,哪个是过时的。
I've done several forms that follow a similar pattern:
two interdependent form fields, let's say "street address" and "location" (lon/lat).
when user fills in one field, the other is updated via an ajax call.
(eg. if the user fills in street address, do a request to a geocode API and put the result in the location field; if the user fills in the location (eg. via a map UI), do a request to a reverse-geocode API and put the result in the address field.
No problem so far, these are easy to hook up to blur and/or focus change events.)The problem occurs if the form is submitted before an ajax call completes. In this case one field will have a correct value and the other will be stale. The handler on the server needs to detect that this has happened and update the stale value. We can't just check for the default value because the user might have changed both fields any number of times.
There are two possible solutions I've thought of, and I don't much like either one. I'd love other suggestions.
Solution 1. Use hidden fields as flags to indicate freshness: set the value to 0 by default, reset it to 0 before the ajax request is sent, and set it to 1 when the response comes back. On the server side, check these fields and recompute any field whose freshness flag is set to 0. There is still a potential race condition here but the window is greatly narrowed. I've used this technique and it works (eg. http://fixcity.org/racks/new/). It is annoying though, as it requires more code on both client and server and is another possible source of bugs.
Solution 2. Use synchronous AJAX calls instead ("SJAX"?). Not appealing since AJAX here is just a UI convenience, it's not strictly necessary for the application to work, so I'd rather not make things feel slow - then it becomes UI *in*convenience.
Solution 3. Always do server-side postprocessing. If it's expensive, use caching to make it cheaper - eg. if the value is not stale, that means the client just made the same request via AJAX so we should have populated the cache if needed during the AJAX handler.
This one currently seems the most appealing to me, although it has two limitations:
it can't be used for things that are not safe and idempotent - eg. if the AJAX request was doing a POST; and it can't even be used for this example because we have two interdependent fields and no way to know which is correct and which is stale.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
当用户按下提交时,让它运行一个验证函数,通过检查表单字段和 ajax 调用的状态(设置一个标志,例如 ajaxBusy)来决定表单所处的状态。
When the user presses submit, have it run a validation function that decides what state the form is in by examining the form fields and the state of the ajax call (set a flag, such as ajaxBusy).
您可以增强 AJAX 调用以禁用表单提交按钮并将全局变量设置为在表单提交时检查的
true
〜这样用户无法提交AJAX 完成之前的表单。为了用户界面的缘故,我会添加一个加载图形。You could enhance your AJAX call to both disable the form submit button and set a global var to to
true
that is checked on form submit~ That way the user can't submit the form before AJAX completes. I would add a loading graphic for UI sake.无论如何,您应该验证服务器端提交的内容。如果两个字段是1-1相关的,那么你可以指定其中一个为“master”,并单独提交,而另一个则在服务器端计算。
You should validate what is submitted on server-side anyway. If both fields are related 1-1, then you can designate one of them as "master", and submit it alone, while the other one is calculated server-side.