2013-02-26 60 views
1

我正在验证包含用户配置文件信息的表单,并且希望与我的服务器一起检查用户指定的用户名是否已被使用。我已经定义了一个验证方法,如下所示:为什么我的验证ajax调用延迟整个验证方法?

$.validator.addMethod(
    'check_username', 
    function(value, element, param) { 
     console.log('starting'); 
     var name_is_in_use = 0; 

     // Start the throbber. 
     $('form#user-profile-form input#edit-name').addClass('searching'); 

     // Hit the server and see if this name is already in use by someone else. 
     $.ajax({ 
      url: '/checkusername/' + value + '/" . $form['#user']->uid . "', 
      dataType: 'json', 
      data: {}, 
      async: false, 
      success: 
       function(data) { 
         console.log('back from the server'); 
         name_is_in_use = data; // unnecessary, but whatever 

         // Kill the throbber 
         $('form#user-profile-form input#edit-name').removeClass('searching'); 
        }, 
     }); 

     return name_is_in_use; 
    }, 
    'Sorry, but this username is already in use.'); 

总的来说,验证过程起作用;我遇到的麻烦是在输入字段上连接一个“忙碌”的悸动者以正常工作 - 悸动者永远不会从其正常状态变为忙碌状态。但是,在服务器上添加一些sleep()调用以夸大实际发生的情况后,我所看到的是这两个console.log语句同时出现在控制台中 - 在调用服务器之后已经完成。这就解释了为什么我没有看到跳动的变化 - .searching类在添加后立即被删除。但我不明白的是,为什么我没有看到我在想什么应该要发生的事情:

  1. 我点击浏览器领域火验证方法。
  2. console.log('starting')显示在控制台中
  3. 跳动者打开。
  4. 有一个暂停,而服务器被调用,睡了一下, 返回其值,
  5. console.log('back')显示了在该活动指示器被关闭控制台

相反,我得到这个(忽略活动指示器类的变化):

  1. 我点击浏览器领域火验证方法。
  2. 有一个暂停,而服务器被调用,睡了一下, 返回其值,
  3. console.log('starting')显示了在控制台,然后,无延迟,
  4. console.log('back')在控制台中显示出来

步骤3和4几乎同时发生。

我对此非常疑惑 - 看起来整个执行程序被ajax调用阻止了,这对我来说根本毫无意义。任何人都可以提供一些见解吗?谢谢!

+0

'async:false'应该是'async:true' - 更多地阅读这个设置。异步设置为false会使请求异步。 http://api.jquery.com/jQuery.ajax/ – Pebbl 2013-02-26 23:31:30

+0

请参阅:http://stackoverflow.com/a/13579061/594235 – Sparky 2013-02-27 00:13:03

回答

3

这很简单,那是因为你在你的$.ajax通话设置asyncfalse

您正在制作同步请求,并且通常在完成此类事情时,Web浏览器在等待来自服务器的响应时往往看起来像悬挂。

+0

谢谢 - 接近但不完全。我将async更改为true,并将“return name_is_in_use”移至成功处理程序中。好消息是,throbber现在正常工作,但是,由于ajax调用不再是异步的,验证方法立即返回一个“假”值。通过console.log,我可以看到ajax调用做正确的事情,但它不再为验证系统提供价值。有没有办法解决这个问题? – 2013-02-26 23:48:12

+0

是的,有。你需要做一个异步验证。我从来没有说你的验证是在做了适当的AJAX请求之后才会起作用:) – Alexander 2013-02-26 23:49:52

+0

@JimMiller,'data'格式是什么? Validate插件的自定义方法正在寻找'return true'或'return false'。 'return 1'或'return 0'也起作用。 – Sparky 2013-02-26 23:50:43

0

好吧,我有一些不仅有效,但似乎相对原则。有人认为它可能对别人有用......

$('form#user-profile-form').validate({ 
    debug: true, 
    rules: { 
     name: { 
      required: true, 
      regexp: /\W/, 
      remote: { 
       url: '/checkusername', 
       type: 'post', 
       data: { 
        username: function() { return $('#edit-name').val() }, 
        uid: " . $form['#user']->uid . " 
        }, 
       beforeSend: function (jqXHR, settings) { 
           $('form#user-profile-form input#edit-name').addClass('searching'); 
          }, 
       complete: function (jqXHR, settings) { 
           $('form#user-profile-form input#edit-name').removeClass('searching'); 
          }, 
      } 
     } 
    }, 

    messages: { 
     name: { 
      regexp: '" . USERNAME_VALIDATION_MESSAGE . "', 
      remote: 'Sorry, but this username has been claimed by someone else.', 
      }, 
     ... 
     }, 
    errorPlacement: function(error, element) { 
     switch (element.attr('name')) { 
      case 'name': 
       error.insertAfter('.control-group.form-item-name > label'); 
       $('form#user-profile-form input#edit-name').removeClass('searching'); 
       break; 
      ... 

注意到这里的有些事情:

  • 繁重通过remote选项,其中,作为 医生说做,是为这样的东西。 另一端的代码如果用户名可用则url返回JSONed 1/true,如果不是,则返回 。
  • beforeSend处理程序在服务器调用发生之前在验证的开头 处打开跳动者。
  • 在用户指定非冲突名称的情况下,complete处理程序会关闭跳动程序。
  • errorPlacement中的removeClass调用关闭 在服务器调用已返回并且报告了 错误的情况下跳动。
  • 因为我有username两个规则 - 对已在使用的试验和 正则表达式测试,以确保指定的名称是一个“字” - 我要 指定每个相应的消息,在messages部分。

Phew。欢迎评论;感谢所有的帮助!