我有一个页面在继续下一页之前对电子邮件进行AJAX验证,使用HTML5 setCustomValidity()方法[使用旧浏览器的webshims库]。
为了实现这一点,我在$ .ajax()调用中将async选项设置为false以使其同步,阻止页面等待AJAX响应,否则表单在ajax调用返回之前提交,从而呈现验证无效的。
<script>
function validateEmailRegistered(input) {
if (input.setCustomValidity === undefined) return;
var err = 'Email address not found';
$.ajax({
url: 'email-is-registered.php',
data: { email: input.value },
async: false,
success: function(data) {
var ok = data=='true';
input.setCustomValidity(ok ? '' : err)
}
});
}
</script>
<form method="get" action="nextpage.php">
<input name="email" id="email" type="email" required
onChange="validateEmailRegistered(this)">
<button type="submit">go</button>
<form>
我发现从jQuery 1.8开始就不推荐使用async选项。
如果没有async选项,如何实现此阻止操作?
答案 0 :(得分:10)
http://bugs.jquery.com/ticket/11013#comment:40
1.8中已弃用同步ajax请求中的Deferred / Promise功能。支持使用async:false的$ .ajax方法,但必须使用回调参数而不是
.then
或.done
等Promise方法。
因此,如果您使用的是success / complete / error处理程序,您仍然可以使用async:false
。更多信息在上面的jquery票。
答案 1 :(得分:2)
从jQuery 1.8开始,使用async:false和jqXHR($ .Deferred) 弃用;您必须使用完整/成功/错误回调。
我觉得这有点烦人......开发人员应该给选择与async: false
进行阻止调用,如果平台允许的话 - 为什么限制它?我只是设置一个超时以最小化挂起的影响。
尽管如此,我现在正在1.8中使用一个队列,它是非阻塞的,并且工作得非常好。 Sebastien Roch创建了一个易于使用的实用程序,允许您排队功能并运行/暂停它们。 https://github.com/mjward/Jquery-Async-queue
queue = new $.AsyncQueue();
queue.add(function (queue) { ajaxCall1(queue); });
queue.add(function (queue) { ajaxCall2(queue); });
queue.add(function() { ajaxCall3() });
queue.run();
在前2个函数中,我将queue
对象传递给调用,这是调用的样子:
function ajaxCall1(queue) {
queue.pause();
$.ajax({
// your parameters ....
complete: function() {
// your completing steps
queue.run();
}
});
}
// similar for ajaxCall2
注意每个函数开头的queue.pause();
,queue.run()
在complete
语句结束时继续执行队列。
答案 2 :(得分:0)
我认为无论如何你都会在提交时进行完整的表单验证,所以如果你的类型的电子邮件验证被中断,并且优先考虑表单提交,也许没问题。
我认为我做的是在用户提交表单时中止'validateEmailRegistered'AJAX请求。然后,像往常一样执行完整的服务器端表单验证 - 包括电子邮件验证。
我对你的类型验证的理解是,它是一种精确的,而不是替代在提交时验证表单。因此,阻止表单提交对我来说没有意义。
答案 3 :(得分:0)
我认为你需要改变它的工作原理。不要试图阻止,而是接受非阻塞。
我会这样做: - 保持电子邮件的验证;使它异步。当它有效时,在变量的某处设置一个标志就知道它没问题。 - 在form.submit()上添加一个回调来检查电子邮件是否正常(使用变量),如果不是,则阻止提交。
这样您就可以在不冻结Web浏览器UI的情况下保持异步调用。
- [编辑] -
这是我刚刚根据你已经拥有的内容编写的一些快速代码。
为了您的信息,我们发明了一种名为“承诺”(期货和延期是其他条款)的编程概念来解决您所遇到的问题。
这是一篇关于它是什么以及如何在JavaScript中使用它们的文章(使用dojo或jQuery):http://blogs.msdn.com/b/ie/archive/2011/09/11/asynchronous-programming-in-javascript-with-promises.aspx
<script>
function validateEmailRegistered(input) {
if (input.setCustomValidity === undefined) return;
var err = 'Email address not found';
$.ajax({
url: 'email-is-registered.php',
data: { email: input.value },
success: function(data) {
var ok = data=='true';
input.setCustomValidity(ok ? '' : err);
// If the form was already submited, re-launch the check
if (form_submitted) {
input.form.submit();
}
}
});
}
var form_submitted = false;
function submitForm(form) {
// Save the user clicked on "submit"
form_submitted = true;
return checkForm(form);
}
function checkForm(form, doSubmit) {
if (doSubmit) {
form_submitted = true;
}
// If the email is not valid (it can be delayed due to asynchronous call)
if (!form.email.is_valid) {
return false;
}
return true;
}
</script>
<form method="get" action="nextpage.php" onsumbit="return submitForm(this);">
<input name="email" id="email" type="email" required
onChange="validateEmailRegistered(this)">
<button type="submit">go</button>
<form>
答案 4 :(得分:0)
如果在确认电子邮件有效期之前确实没有让他们提交表单,请使用disabled
属性启动提交按钮,然后设置回调设置$('form button').removeAttr('disabled');
话虽如此,我和其他人一起 - 让他们提交表格!通常人们会把它弄好,你可以毫无错误地通过它们......
答案 5 :(得分:0)
您可以异步执行此操作。
创建一个全局变量,我称之为ajax_done_and_successful_flag, 你在开始时初始化为false 程序。您将在各种情况下将此设置为true或false 您的Ajax功能中的位置,例如您的Ajax成功 函数或您的Ajax错误函数。
然后你需要在你的底部添加一个提交处理程序 验证功能。
submitHandler: function(form) {
if (ajax_done_and_successful_flag === true) {
form.submit()
}
}
问题是代码没有以线性方式执行
在你的代码中放入一堆Firebug的console.log语句
观察执行顺序。你会看到你的
Ajax响应最后会回来,或者在它感觉到的时候回复
这就是你需要submitHandler和全局标志的原因
强制验证功能等待正确的Ajax
表单提交前的结果。
从Ajax响应到屏幕的任何输出,
需要在
Ajax函数,如成功函数和
错误功能。
你需要写到同一个位置
作为验证功能的成功/错误功能。
这样Ajax错误消息就与validate函数混合在一起
错误功能。
这个概念看起来有点棘手
保持的想法
介意验证功能中的成功和错误功能
正在写入与成功和错误相同的位置
Ajax调用中的函数,没关系,就是这样
应该是。
我的错误消息的位置就在旁边的位置
用户输入输入。这创造了一个很好的用户体验
我认为你要求的。
这是我的代码示例。我简化了它。
我正在运行jQuery-1.7.1
和jQuery验证插件1.6
我正在使用Firefox 14.0.1,我也试过了
它在Chrome 21.0上成功了。
var ajax_done_and_successful_flag = false;
// Add methods
...
$.validator.addMethod("USERNAME_NOT_DUPLICATE", function (value, element) {
return this.optional(element) || validate_username_not_duplicate( );
},
"Duplicate user name.");
// validate
$(document).ready(function ( ) {
$('#register_entry_form form').validate({
rules: {
username: {
required: true,
minlength: 2,
maxlength: 20,
USERNAME_PATTERN: true,
USERNAME_NOT_DUPLICATE: true
},
...
errorPlacement: function (error, element) {
element.closest("div").find(".reg_entry_error").html(error);
},
success: function(label) {
label.text('Success!');
} ,
submitHandler: function(form) {
if (ajax_done_and_successful_flag === true ) {
form.submit();
}
}
});
});
/* validation functions*/
function validate_username_not_duplicate() {
var username_value = $('#username').val(); // whatever is typed in
$.ajax({
url: "check_duplicate_username.php",
type: "POST",
data: { username: username_value },
dataType: "text",
cache: false,
//async: false,
timeout: 5000,
error: function (jqXHR, errorType, errorMessage) {
ajax_done_and_successful_flag = false;
if ( errorType === "timeout" ) {
$('#username').closest("div").find(".reg_entry_error").html("Server timeout, try again later" );
} else if ...
},
success: function (retString, textStatus,jqXRH) {
if ( retString === "yes") { // duplicate name
// output message next to input field
$('#username').closest("div").find(".reg_entry_error").html("Name already taken.");
ajax_done_and_successful_flag = false;
} else if ( retString === "no") { // name is okay
// output message next to input field
$('#username').closest("div").find(".reg_entry_error").html("success!");
ajax_done_and_successful_flag = true;
} else {
console.log("in validate_username_duplicate func, success function, string returned was not yes or no." );
$('#username').closest("div").find(".reg_entry_error").html("There are server problems. Try again later.");
ajax_done_and_successful_flag = false;
}
} // end success function
}); // end ajax call
return true; // automatically return true, the true/false is handled in
// the server side program and then the submit handler
}
reg_entry_error是文本输入旁边的位置。 这是表单的简化代码示例。
<label class="reg_entry_label" for="username">Username</label>
<input class="reg_entry_input" type="text" name="username" id="username" value="" />
<span class="reg_entry_error" id="usernameError" ></span>
我希望这能回答你的问题。