每个带有ajax调用的jQuery都会在它完成之前继续

时间:2017-01-18 09:52:44

标签: javascript jquery ajax

我有一些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功能,但我真的不明白如何使它工作。任何帮助表示赞赏。

3 个答案:

答案 0 :(得分:2)

First, write a function that returns an asynchronous promise to give you a value for one dog:

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 '';
            }
        });
    }
}

Then you can write one that handles multiple dogs, also returning a promise (which won't itself be resolved until every dog has been checked):

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

Note that there's no DOM-related code yet. You can now write a function that gets the values from a bunch of DOM inputs and returns them in an array:

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

So now (on submit) you can check your two sets of inputs and then finally when both of these are available, you can examine the results and update the 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
        ...
    });
});

答案 1 :(得分:0)

你是对的,ajax调用就像他们的名字所说的异步。因此,您只能依赖using System; using System.IO; using System.Web; using System.Web.Mvc; namespace ImageUploadCkEditor.Controllers { public class CkEditorUploadController : Controller { const string filesavepath = "~/Content/Uploads/Ckeditor"; const string baseUrl = @"/Content/Uploads/Ckeditor/"; const string scriptTag = "<script type='text/javascript'>window.parent.CKEDITOR.tools.callFunction({0}, '{1}', '{2}')</script>"; public ActionResult Index() { var funcNum = 0; int.TryParse(Request["CKEditorFuncNum"], out funcNum); if (Request.Files == null || Request.Files.Count < 1) return BuildReturnScript(funcNum, null, "No file has been sent"); string fileName = string.Empty; SaveAttatchedFile(filesavepath, Request, ref fileName); var url = baseUrl + fileName; return BuildReturnScript(funcNum, url, null); } private ContentResult BuildReturnScript(int functionNumber, string url, string errorMessage) { return Content( string.Format(scriptTag, functionNumber, HttpUtility.JavaScriptStringEncode(url ?? ""), HttpUtility.JavaScriptStringEncode(errorMessage ?? "")), "text/html" ); } private void SaveAttatchedFile(string filepath, HttpRequestBase Request, ref string fileName) { for (int i = 0; i < Request.Files.Count; i++) { var file = Request.Files[i]; if (file != null && file.ContentLength > 0) { fileName = Path.GetFileName(file.FileName); string targetPath = Server.MapPath(filepath); if (!Directory.Exists(targetPath)) { Directory.CreateDirectory(targetPath); } fileName = Guid.NewGuid() + fileName; string fileSavePath = Path.Combine(targetPath, fileName); file.SaveAs(fileSavePath); } } } } } 功能。一个简单的解决方案是在开始时为母狗和狗初始化一个计数器变量,并在相应的完成函数中递减它直到它达到零。然后,在done函数中,您放置了一个调用错误数组验证的.done。这是UNTESTED代码,以显示我的意思:

if

答案 2 :(得分:0)

您可以使用async lib来管理这些请求并收集结果,然后将结果传递到您可以处理它们的最终回调中。

我还没有尝试过运行此代码,但希望它能让你足够接近,如果还没有那么。

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
});