我有一些jQuery,它使用每个循环来遍历Symfony 3 CRM上重复表格字段中输入的值。有一个$.post会将输入的值发送到一个函数,该函数检查数据库中是否存在重复项,如果是重复项,则会向数组中添加某些内容,否则将添加空白值以表明它不是重复项。完成这些操作后,它将检查最终数组,并将所有错误添加到错误块以显示给用户。

但是,数组似乎总是空白,我相信它是因为它正在运行显示错误的代码,然后才真正完成响应。

这是我的代码:

$('#puppy_form').on('submit', function() {
    var bitch_errors = [];
    var dog_errors = [];
    // NOTE: Bitch and dog names need to be checked differently so we know which error is assigned to which input
    $('.check_bitch_name').each( function(i, obj) {
        // need to check each name for validity and duplication.
        var entered_bitch_name = obj.value;
        var pattern = /^[a-zA-Z,.]+\s[a-zA-Z,.]+(\s[a-zA-Z,.]+){0,}$/;
        if(!pattern.test(entered_bitch_name)) {
            bitch_errors[i+1] = "invalid";
        } else {
            // now to check for duplicates
            $.post('/check-puppy-name', { name: entered_bitch_name }
            ).done(function (response) {
                if(response == 'duplicate') {
                    bitch_errors[i+1] = "duplicate";
                } else {
                    bitch_errors[i+1] = "";
                }
            });
        }
    });
    $('.check_dog_name').each( function(i, obj) {
        // need to check each name for validity and duplication.
        var entered_dog_name = obj.value;
        var pattern = /^[a-zA-Z,.]+\s[a-zA-Z,.]+(\s[a-zA-Z,.]+){0,}$/;
        if(!pattern.test(entered_dog_name)) {
            dog_errors[i+1] = "invalid";
        } else {
            // now to check for duplicates
            $.post('/check-puppy-name', { name: entered_dog_name }
            ).done(function (response) {
                if(response == 'duplicate') {
                    dog_errors[i+1] = "duplicate";
                } else {
                    dog_errors[i+1] = "";
                }
            });
        }
    });


    if(count(bitch_errors) == 0 && count(dog_errors) == 0) {
        return true;
    }

    // loop through the errors and assign them to the correct input
    $.each( bitch_errors, function( key, value ) {
        if (value == "invalid") {
            $('input[name="bitch_name['+key+']"]').parent().addClass('has-error');
            $('input[name="bitch_name['+key+']"]').next('.error-message').html('Names must be at least two words, and only contain letters');
            return false;
        } else if(value == "duplicate") {
            $('input[name="bitch_name['+key+']"]').parent().addClass('has-error');
            $('input[name="bitch_name['+key+']"]').next('.error-message').html('Sorry, this name has already been taken');
            return false;
        }
    });
    $.each( dog_errors, function( key, value ) {
        if(value != "") {
            if (value == "invalid") {
                $('input[name="dog_name['+key+']"]').parent().addClass('has-error');
                $('input[name="dog_name['+key+']"]').next('.error-message').html('Names must be at least two words, and only contain letters');
                return false;
            } else if(value == "duplicate") {
                $('input[name="dog_name['+key+']"]').parent().addClass('has-error');
                $('input[name="dog_name['+key+']"]').next('.error-message').html('Sorry, this name has already been taken');
                return false;
            }
        }
    });

    return false;

});


基本上,它首先检查输入的名称是否有效,然后过帐并检查是否存在重复。问题是,即使它进行了有效性检查(并相应地打印了错误),它似乎也忽略了重复检查,并在它还没有返回第一个响应之前就继续执行。

我如何确保在完成检查之前完成检查并将错误添加到表单?我尝试了其他解决方案,包括尝试在jQuery中实现$.when功能,但我不太了解如何使其正常工作。任何帮助表示赞赏。

最佳答案

首先,编写一个返回异步承诺的函数,为您提供一条狗的价值:

function checkDog(name) {
    var pattern = /^[a-zA-Z,.]+\s[a-zA-Z,.]+(\s[a-zA-Z,.]+){0,}$/;
    if(!pattern.test(name)) {
        return $.Deferred().resolve("invalid");
    } else {
        return $.post('/check-puppy-name', { name: name } )
         .then(function (response) {
            if (response === 'duplicate') {
                return 'duplicate';
            } else {
                return '';
            }
        });
    }
}


然后,您可以编写一个处理多只狗的代码,并返回一个承诺(只有在检查完每只狗之后,它才会被解决):

function checkDogs(array) {
    return $.when.apply($, array.map(checkDog));
}


注意,还没有与DOM相关的代码。现在,您可以编写一个函数,该函数从一堆DOM输入中获取值并以数组形式返回它们:

function getInputValues($selector) {
    return $selector.get().map(function(el) {
        return el.value;
    });
}


因此,现在(在submit上),您可以检查两组输入,然后最后在两个输入都可用时,可以检查结果并更新DOM:

$('#puppy_form').on('submit', function() {

    var bitch_names = getInputValues($('.check_bitch_name'));
    var dog_names = getInputValues($('.check_dog_name'));

    var bitch_promises = checkDogs(bitch_names);
    var dog_promises = checkDogs(dog_names);

    $.when(bitch_promises, dog_promises).then(function(bitch_errors, dog_errors) {
        // update the DOM based on the passed arrays
        ...
    });
});

10-04 15:47
查看更多