I'm working on validating CAPTCHA input using AJAX. I realized I couldn't return a value from the success handler on the AJAX call, so I created a global variable so the success handler and the validation function could talk to eachother. But it's not working in the most mistifying way. First, the code:
我正在使用AJAX验证CAPTCHA输入。我意识到我无法从AJAX调用的成功处理程序返回一个值,因此我创建了一个全局变量,因此成功处理程序和验证函数可以相互通信。但它并没有以最令人费解的方式运作。一,代码:
jQuery('#contact').submit(function(event) {
if (validate_form())
{
submit_form(event);
}
else
{
return false;
}
});
var valid = true;
function validate_form()
{
valid = true;
// test form stuff here
// if something goes wrong valid will be set to false
if (!valid)
{
alert("form is not valid, refreshing captcha");
// refresh form
// ....
}
else
{
alert("form is valid, checking captcha");
check_recaptcha();
}
alert("finally, form is:" + valid);
return valid;
}
function check_recaptcha()
{
alert("checking captcha now");
// take only recaptcha values from form
var recaptcha_vals = jQuery(':input[name^="recaptcha"]').serialize();
jQuery.post('recaptcha.php', recaptcha_vals, function(data) {
alert("recaptcha post has succeeded!");
if (data == '1\n' /*success!*/)
{
alert("recaptcha is correct!");
jQuery('#recaptcha_error').empty();
}
else
{
alert("recaptcha is incorrect!");
show_recaptcha();
jQuery('#recaptcha_error').html("<p class=\"error\">CAPTCHA was incorrect, please try again.</p>");
valid = false;
}
});
}
I tested this code with nothing in the CAPTCHA input field (an obviously incorrect value). According to the alerts, each part of the code went through as expected, except valid
was still true
after check_recaptcha()
executes, even though I know the "incorrect" branch was followed. So question #1 is: Why isn't the event handler able to set valid
to false
?
我在CAPTCHA输入字段中没有任何内容测试此代码(显然是不正确的值)。根据警报,代码的每个部分都按预期完成,除了在执行check_recaptcha()之后有效仍然为真,即使我知道遵循“不正确”分支。问题#1是:为什么事件处理程序不能将有效设置为false?
Here's where it gets weird. In the above scenario, the form doesn't submit, even though validate_form()
returns true
(according to the alerts). However, when I comment out all the alerts and try it again with the exact same inputs, then the form DOES submit. So question #2 is: What's up with THAT? #1 is more important though.
这就是它变得奇怪的地方。在上面的场景中,即使validate_form()返回true(根据警报),表单也不会提交。但是,当我注释掉所有警报并使用完全相同的输入再次尝试时,表单将提交。问题#2是:这有什么用? #1更重要。
2 个解决方案
#1
2
The point of asynchronous callbacks is that the jQuery.post()
will return immediately, without waiting for a reply from the recaptcha service. So when you make your "finally" alert, the recapthcha transation is still going on, and your callback will be called on when it is finished. Then, while your alert is waiting for you to click OK, the recaptcha reply arrives and your callback runs. If you comment out the alert, your submit handler will complete before the callback gets a chance to set valid to false.
异步回调的重点是jQuery.post()将立即返回,而不等待recaptcha服务的回复。因此,当您发出“最终”警报时,仍然会进行回溯转换,并在完成后调用您的回调。然后,当您的警报等待您单击“确定”时,重新接收回复将到达并且您的回叫将运行。如果您注释掉警报,则在回调有机会将有效设置为false之前,您的提交处理程序将完成。
That's why you need to supply a callback in the first place, rather than just reading a return value.
这就是为什么你需要首先提供一个回调,而不是只是读取一个返回值。
Also: You are aware that checking a captcha on the client side is pointless, unless you repeat the check on the server side later, right? (Arguably it's pointless even if you repeat it on the server. The point of client-side validation is to give the user instant feedback on trouble without waiting for a network roundtrip to the server. If you wait to submit until you've completed a roundtrip to check the captcha, you have accomplished nothing but doubling the response time in the successful case. The only exception I can think of is if your form contains really large amounts of data that would take appreciable time to transfer).
另外:您知道在客户端检查验证码是没有意义的,除非您稍后在服务器端重复检查,对吧? (可以说,即使你在服务器上重复它也没有意义。客户端验证的目的是为用户提供有关故障的即时反馈,而无需等待网络往返服务器。如果你等到提交直到你完成了往返检查验证码,你已经完成了成功案例中的响应时间加倍。我唯一能想到的例外是你的表单中是否包含大量需要花费大量时间进行传输的数据。
#2
0
I found my answer here: Javascript Local vs Global. I went against that answer's advice, though, and did set my request to be synchronous, which worked fine in the context of my application.
我在这里找到了答案:Javascript Local vs Global。不过,我反对那个答案的建议,并确实将我的请求设置为同步,这在我的应用程序环境中运行良好。
#1
2
The point of asynchronous callbacks is that the jQuery.post()
will return immediately, without waiting for a reply from the recaptcha service. So when you make your "finally" alert, the recapthcha transation is still going on, and your callback will be called on when it is finished. Then, while your alert is waiting for you to click OK, the recaptcha reply arrives and your callback runs. If you comment out the alert, your submit handler will complete before the callback gets a chance to set valid to false.
异步回调的重点是jQuery.post()将立即返回,而不等待recaptcha服务的回复。因此,当您发出“最终”警报时,仍然会进行回溯转换,并在完成后调用您的回调。然后,当您的警报等待您单击“确定”时,重新接收回复将到达并且您的回叫将运行。如果您注释掉警报,则在回调有机会将有效设置为false之前,您的提交处理程序将完成。
That's why you need to supply a callback in the first place, rather than just reading a return value.
这就是为什么你需要首先提供一个回调,而不是只是读取一个返回值。
Also: You are aware that checking a captcha on the client side is pointless, unless you repeat the check on the server side later, right? (Arguably it's pointless even if you repeat it on the server. The point of client-side validation is to give the user instant feedback on trouble without waiting for a network roundtrip to the server. If you wait to submit until you've completed a roundtrip to check the captcha, you have accomplished nothing but doubling the response time in the successful case. The only exception I can think of is if your form contains really large amounts of data that would take appreciable time to transfer).
另外:您知道在客户端检查验证码是没有意义的,除非您稍后在服务器端重复检查,对吧? (可以说,即使你在服务器上重复它也没有意义。客户端验证的目的是为用户提供有关故障的即时反馈,而无需等待网络往返服务器。如果你等到提交直到你完成了往返检查验证码,你已经完成了成功案例中的响应时间加倍。我唯一能想到的例外是你的表单中是否包含大量需要花费大量时间进行传输的数据。
#2
0
I found my answer here: Javascript Local vs Global. I went against that answer's advice, though, and did set my request to be synchronous, which worked fine in the context of my application.
我在这里找到了答案:Javascript Local vs Global。不过,我反对那个答案的建议,并确实将我的请求设置为同步,这在我的应用程序环境中运行良好。