繁体   English   中英

每个带有ajax调用的jQuery将在完成之前继续进行

[英]jQuery each with ajax call will continue before it's finished

我有一些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
        ...
    });
});

没错,ajax调用就像它们的名字说的那样异步。 因此,您只能依靠.done函数。 一个简单的解决方案是在母犬和狗的开头初始化一个计数器变量,然后在完成的函数中将其递减直到其达到零。 然后,也在完成函数中,放置一个if来调用错误数组的验证。 这是未测试的代码,以显示我的意思:

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

    /* 
       here you get the initial count for bitches and dogs 
    */
    var bitch_count = $('.check_bitch_name').length;
    var dog_count = $('.check_dog_name').length;

    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] = "";
                }

                /*
                    now on every checked name you decrement the counter
                    and if both counters reach zero you can be sure you
                    checked all and only now you call your validation
                */
                bitch_count--;
                if(bitch_count === 0 && dog_count === 0) {
                    return validateErrors();
                }

            });
        }
    });
    $('.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] = "";
                }

                /*
                    same here
                */                    
                dog_count--;
                if(bitch_count === 0 && dog_count === 0) {
                    return validateErrors();
                }

            });
        }
    });
}

/*
    ...and finally all code that should be processed after the ajax calls
*/
function validateErrors() {
    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;

});

您可以使用异步库来管理这些请求并收集结果,然后将结果传递到最终的回调中,您可以在其中处理这些请求。

我没有尝试运行此代码,但希望它能使您足够接近(如果还没有的话)。

async.parallel({
    bitch_errors: function(callback) {
       var bitch_errors = [];

       async.forEachOf($('.check_bitch_name'), function(obj, i, cb) {
           // 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";
               cb();
           } 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] = "";
                 }
                 cb();
              });
          }
       }, function () {
           callback(null, bitch_errors);
       });
    },
    dog_errors: function(callback) {
       var dog_errors = [];

       async.forEachOf($('.check_dog_name'), function(obj, i, cb) {
           // 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";
               cb();
           } 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] = "";
                   }
                   cb();
              });
          }
       }, function () {
           callback(null, dog_errors);
       });
    }
}, function(err, results) {
    // you can now access your results like so

    if(count(results.bitch_errors) == 0 && count(results.dog_errors) == 0) {
    // ... rest of your code
});

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM