如何在没有async = false的情况下执行jQuery阻止AJAX调用?

我有一个页面在继续下一页之前对电子邮件进行AJAXvalidation,使用HTML5 setCustomValidity()方法[使用旧浏览器的webshims库]。

为此,我在$ .ajax()调用中将async选项设置为false以使其同步,阻止页面等待AJAX​​响应,否则表单在ajax调用返回之前提交,从而使validation无效。

 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) } }); }  

我看到从jQuery 1.8开始不推荐使用async选项。

如果没有async选项,如何实现此阻止操作?

http://bugs.jquery.com/ticket/11013#comment:40

在1.8中已弃用同步ajax请求中的Deferred / Promisefunction。 支持使用async:false的$ .ajax方法,但必须使用回调参数而不是Promise方法,例如.then.done

因此,如果您使用的是success / complete / error处理程序,您仍然可以使用async:false 。 更多信息在上面的jquery票。

从jQuery 1.8开始,不推荐使用async:false和jqXHR($ .Deferred); 您必须使用完整/成功/错误回调。

http://api.jquery.com/jQuery.ajax/(async section)

我发现这有点烦人……开发人员应该选择使用async: false进行阻塞调用async: false如果平台允许的话,可以使用async: false – 为什么要限制它? 我只是设置一个超时来最小化挂起的影响。

尽管如此,我现在在1.8中使用队列,这是一个非阻塞的,并且工作得非常好。 Sebastien Roch创建了一个易于使用的实用程序,允许您排队function并运行/暂停它们。 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语句的末尾继续执行队列。

我假设你无论如何都会在提交时进行完整的表单validation,所以如果你的类型的电子邮件validation被中断,并且优先考虑表单提交,也许没问题。

我想我做的是在用户提交表单时中止’validateEmailRegistered’AJAX请求。 然后,像往常一样执行完整的服务器端表单validation – 包括电子邮件validation。

我对你的类型validation的理解是,它是一种精确的,而不是在提交时validation表单的替代品。 因此,阻止表单提交对我来说没有意义。

如果你确实没有让他们提交表单,直到你检查了电子邮件的有效性,请启动你带有disabled属性的提交按钮,然后设置回调设置$('form button').removeAttr('disabled');

话虽这么说,我和其他人在一起 – 让他们提交表格! 通常人们会把它弄好并且你通过它们没有错误……

我想你需要改变它的工作原理。 不要试图实现阻止,而是拥抱非阻塞。

我会这样做: – 保持电子邮件的validation; 使它异步。 当它有效时,在变量的某处设置一个标志就知道它没问题。 – 在form.submit()上添加一个回调来检查电子邮件是否正常(使用变量),如果不是,则阻止提交。

这样,您可以在不冻结Web浏览器UI的情况下保持异步调用。

– [编辑] –

这是我刚刚根据你已经拥有的内容编写的一些快速代码。

为了您的信息,我们发明了一种名为“承诺”(期货和延期是其他术语)的编程概念,以解决您所遇到的问题。

这是一篇关于它是什么以及如何在JavaScript中使用它们的文章(使用dojo或jQuery): http : //blogs.msdn.com/b/ie/archive/2011/09/11/asynchronous-programming-in-javascript -with-promises.aspx

     

您可以异步执行此操作。

创建一个全局变量,我称之为ajax_done_and_successful_flag,在程序开始时将其初始化为false。 您将在Ajax函数的各个位置(例如Ajax成功函数或Ajax错误函数)将其设置为true或false。

然后,您需要在validationfunction的底部添加提交处理程序。

 submitHandler: function(form) { if (ajax_done_and_successful_flag === true) { form.submit() } } 

问题是代码没有以线性方式执行。
在你的代码中放入一堆Firebug的console.log语句。
观察执行顺序。 你会看到你的
Ajax响应最后会回来,或者只要感觉就好。
这就是你需要submitHandler和全局标志的原因
强制validate函数等待正确的Ajax
表单提交前的结果。

从Ajax响应到屏幕的任何输出都需要在Ajax函数中完成,例如成功函数和错误函数。
您需要写入与validate函数的成功/错误函数相同的位置。
这样,Ajax错误消息与validate函数的错误函数混合在一起。
这个概念看起来有点棘手。
要记住的想法是,validate函数中的成功和错误函数正在写入与Ajax调用中的成功和错误函数相同的位置,这没关系,应该是这样的。
我的错误消息的位置就在用户键入输入的位置旁边。 这创造了我认为您要求的良好用户体验。

这是我的代码示例。 我简化了它。

我正在运行jQuery-1.7.1
和jQueryvalidation插件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是文本输入旁边的位置。 这是表单的简化代码示例。

     

我希望这回答了你的问题。