现代浏览器中的表单发布行为是否发生了变化? (或者浏览器如何处理双击)
背景:我们正在编写一个注册/支付页面,我们的理念是首先在服务器端编写所有验证和错误检查代码,然后添加客户端验证作为第二步(无阻碍的 jQuery )。
我们想要禁用服务器端的双击,因此我们编写了一些锁定、线程安全的代码来处理同时发帖/竞争条件。当我们尝试测试这一点时,我们意识到我们无法导致同时发生帖子或竞争条件。
我认为(无论如何在较旧的浏览器中)双击提交按钮的工作原理如下:
- 用户双击提交按钮。
- 浏览器在第一次单击时发送帖子
- 在第二次单击时,浏览器取消/忽略初始帖子,并启动第二个帖子(在第一个帖子返回响应之前)。
- 浏览器等待第二个帖子返回,忽略最初的帖子响应。
我认为从服务器端来看,它看起来像这样:服务器同时收到两个发布请求,执行并响应它们(不知道没有人在监听第一个响应)。
根据我们的测试(FireFox 3.0、IE 8.0),实际发生的情况是这样的:
- 用户双击提交按钮
- 浏览器发送第一次点击的帖子
- 浏览器将第二次点击排队,但等待第一次点击的响应。
- 响应从第一次单击返回(响应被忽略?)。
- 浏览器会发送第二次点击的帖子。
因此,从服务器端来看:服务器接收一个它执行并响应的帖子。然后,服务器接收第二个请求,并执行并响应。
我的问题是,这一直都是这样吗(我快疯了)?或者这是现代浏览器中的一个新功能,可以防止同时发布到服务器?
似乎对于服务器端双击预防,我们不必担心同时发布或竞争条件。只需要担心排队的帖子。
Background: We are in the process of writing a registration/payment page, and our philosophy was to code all validation and error checking on the server side first, and then add client side validation as a second step (un-obstructive jQuery).
We wanted to disable double clicks server side, so we wrote some locking, thread-safe code to handle simultaneous posts/race conditions. When we tried to test this, we realized that we could not cause a simultaneous post or race condition to occur.
I thought that (in older browsers anyway) double clicking a submit button worked as follows:
- User double clicks submit button.
- Browser sends a post on the first click
- On the second click, browser cancels/ignores initial post, and initiates a second post (before the first post has returned with a response).
- Browser waits for second post to return, ignoring initial post response.
I thought that from the server side it looked like this: Server gets two simultaneous post requests, executes and responds to them both (unaware that no one is listening to the first response).
From our testing (FireFox 3.0, IE 8.0) this is what actually happens:
- User double clicks submit button
- Browser sends a post for the first click
- Browser queues up second click, but waits for the response from the first click.
- Response returns from first click (response is ignored?).
- Browser sends a post for the second click.
So from a server side: Server receives a single post which it executes and responds to. Then, server receives a second request which it executes and responds to.
My question is, has this always worked this way (and I'm losing my mind)? Or is this a new feature in modern browsers that prevents simultaneous posts to be sent to the server?
It seems that for server side double click prevention, we don't have to worry about simultaneous posts or race conditions. Only need to worry about queued up posts.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您需要处理的类似情况(javascript禁用提交按钮解决方案未涵盖)是用户单击“提交”,服务器处理请求,但在处理过程中用户的互联网连接出现故障(可能是他们正在驶入隧道的火车上)。
当火车驶出隧道时,用户不知道他们的交易是否成功 - 他们按下了按钮,但页面上没有任何变化(或者可能他们得到了“再试一次”页面)。他们自然会再次单击“提交”(或“重试”按钮)。
处理这种情况的最佳方法是在表单中(在隐藏字段中)包含唯一的交易 ID。随机生成这个id,当交易成功处理时,将其存储在数据库中已完成交易的列表中。
然后,当您收到 POST 时,检查该事务是否已被看到 - 如果是,则直接跳到状态页面。粗略地说:
这样做的优点是(假设您有一个正确支持交易的数据库 - 并且因为您正在处理付款,我希望您这样做!)您不需要执行任何类型的线程或锁定 - 事情“正常工作” 。
(尽管要小心 - 如果存在并发问题,某些数据库系统可以任意中止您的事务 - 但这种(罕见)情况可以使用重试循环轻松处理......)
至于测试浏览器的双击:它是否会产生任何影响?如果您在两次“提交”点击之间按“停止”按钮,有什么区别?
A similar situation that you need to handle (that the javascript disable-submit-button solution doesn't cover) is the one where the user clicks Submit, the server processes the request, but while it's processing the user's internet connection goes down (perhaps they're on a train going into a tunnel).
When the train comes out of the tunnel, the user doesn't know whether their transaction succeeded or not - they pressed the button, but nothing changed on the page (or perhaps they got a "Try again" page). The natural thing for them to do is click Submit again (or the "Try again" button).
The best way to handle this situation is to include a unique transaction id in the form (in a hidden field). Generate this id randomly, and when a transaction is successfully processed, store it in the database in a list of completed transactions.
Then when you get a POST, check whether this transaction has already been seen - and if it has, skip straight to the status page. Roughly:
This has the advantage that (provided you have a database that properly supports transactions - and since you're processing payments I hope you do!) you don't need to do any sort of threading or locking - things "just work".
(though be careful - some database systems can arbitrarily abort your transactions if there is a concurrency problem - but this (rare) situation is easily dealt with using a retry loop...)
As to testing double clicks from browsers: does it make any difference if you press the "stop" button between the two "submit" clicks?
这可能是一个愚蠢的回应,但为什么不直接用 JavaScript 禁用提交按钮,这样你就不必担心多次点击。我通常在我制作的大多数表格上这样做,它似乎解决了问题。
你已经说过你正在使用 javascript,所以这不是问题,对吗?
this may be a stupid response, but why dont you just disable the submit button with javascript on click, so you dont have to worry about multiple clicks. i usually do this on most forms i make and it seems to solve the problem.
you already said you are using javascript so thats not the issue right?
只要请求处于连接或发送阶段,在第一次提交期间单击“提交”就会取消该请求,并在服务器“不知情”的情况下启动一个新请求。
As long as the request is in its connecting or sending stage, clicking on submit during the first submission cancels the request, starting a new one without the server 'knowing'.