1

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

$.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 语句同时出现在控制台中——在调用服务器之后已经完成。这就解释了为什么我没有看到 throbber 变化——.searching该类在添加后立即被删除。但我不明白的是为什么我没有看到我认为应该发生的事情:

  1. 我单击浏览器中的字段以触发验证方法。
  2. console.log('starting')出现在控制台中
  3. 颤动器被打开。
  4. 服务器被调用时有一个暂停,稍微休眠,并返回它的值,
  5. console.log('back')出现在控制台中
  6. 颤动器被关闭。

相反,我得到了这个(忽略 throbber 类的变化):

  1. 我单击浏览器中的字段以触发验证方法。
  2. 服务器被调用时有一个暂停,稍微休眠,并返回它的值,
  3. console.log('starting')出现在控制台中,然后,没有延迟,
  4. console.log('back')出现在控制台中

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

我对此感到非常困惑——看起来处理程序的整个执行都被 ajax 调用所阻碍,这对我来说根本没有意义。有人可以提供一些见解吗?谢谢!

4

2 回答 2

3

这很简单,那是因为您在通话中设置async为。false$.ajax

您正在发出一个同步请求,通常当这样的事情完成时,Web 浏览器在等待来自服务器的响应时往往看起来像挂起。

于 2013-02-26T23:32:33.710 回答
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,否则返回 0/false。
  • 在服务器调用发生之前,beforeSend处理程序在验证的一开始就打开 throbber。
  • complete在用户指定了非冲突名称的情况下,处理程序会关闭颤动器。
  • 在服务器调用返回并报告错误的情况下,调用关闭会关闭颤动器removeClasserrorPlacement
  • 由于我有两个规则username——已经在使用的测试和一个正则表达式测试以确保指定的名称是一个“单词”——我必须在该messages部分中为每个规则指定适当的消息。

呸。欢迎评论;感谢大家的帮助!

于 2013-02-27T02:35:50.543 回答