为什么我的验证ajax调用延迟整个验证方法?

时间:2013-02-26 23:30:12

标签: jquery jquery-validate

我正在验证包含用户个人资料信息的表单,我想查看我的服务器,看看用户指定的用户名是否已被使用。我已经定义了一个类似的验证方法:

$.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')显示在控制台中
  6. 悸动者被关闭了。
  7. 相反,我得到了这个(忽略了throbber类的变化):

    1. 我单击浏览器中的字段以激活验证方法。
    2. 服务器被调用时有一个暂停,睡了一会儿,然后 返回其值,
    3. console.log('starting')显示在控制台中,然后毫不拖延地显示
    4. console.log('back')显示在控制台中
    5. 步骤3和4几乎同时发生。

      我真的对此感到困惑 - 看起来处理程序的整个执行都被ajax调用所阻碍,这对我来说毫无意义。任何人都可以提供一些见解吗?谢谢!

2 个答案:

答案 0 :(得分:3)

这很简单,因为您在async来电中将 false 设置为 $.ajax

您正在发出同步请求,通常在完成此类操作后,Web浏览器在等待服务器响应时往往看起来像挂起一样。

答案 1 :(得分: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选项完成繁重的工作 doc说,这是为了这样的东西。另一端的代码 如果用户名可用,则url返回JSONed 1 / true,并且 0 / false如果不是。
  • beforeSend处理程序在开始时打开了悸动者 在服务器调用发生之前进行验证。
  • complete处理程序会在那些情况下关闭throbber 用户指定了非冲突名称。
  • removeClass中的errorPlacement调用关闭了username 在那些服务器调用已经返回的情况下出现问题 报告错误。
  • 由于我在messages上有两条规则 - 已经在使用的测试AND a 正则表达式测试,以确保指定的名称是一个“单词” - 我必须 在{{1}}部分为每个部分指定相应的消息。

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