2017-01-18 55 views
1

我有一些jQuery,它使用每个循环来检查在Symfony 3 CRM上的重复表单字段中输入的值。有一个$.post它将输入的值发送到一个函数,该函数检查数据库中的重复项,如果它是重复项,则会向数组中添加一些内容,否则会添加一个空值以指示它不是重复项。完成这些操作后,它会检查最终数组并将任何错误添加到错误块以显示给用户。每个jQuery调用都会在完成之前继续运行

但是,它似乎总是空白,我相信它是因为它运行的代码显示错误之前,它实际上完成获取响应。

这里是我的代码:

$('#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功能,但我并不真正了解如何使其工作。任何帮助赞赏。

回答

2

首先,编写返回异步承诺给你一个价值一个狗功能:

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 
     ... 
    }); 
}); 
+0

我真的不明白这一点 - checkDogs的含义是什么?如果我写这个,这意味着之后没有别的东西会运行,因为它有回报吗? –

+0

@MichaelEmerson唯一需要在你的'submit'回调中的位是两个调用'checkInputs'和最后一个'$ .when'的块。正如你已经猜测的那样,直到'$ .post'调用全部完成之后,这些数组才可用,'$ .when'调用处理该同步。 – Alnitak

+0

好吧,那很好,但checkDogs(数组)是什么?如果我补充一点,它会在第一个括号之前抛出一个错误,指出“期待换行符或分号”。另外,由于返回,getInputValues永远不会被达到? –

0

你说得对,ajax调用就像他们的名字说异步。因此,您只能依靠.done函数。一个简单的解决方案是在母狗和狗的开始初始化一个计数器变量,并在相应的函数中减小它直到它达到零。然后,在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; 

}); 
+1

我强烈推荐使用'$ .when'来代替。你也可以使用'$ .fn.map'而不是'$ .fn.forEach'生成一个承诺数组传递给'$ .when' – Alnitak

+0

@Alnitak我是'$ .when'的新手,所以使用作为标志的柜台是我想出的第一件事。但偷看到jquery文档,这绝对是一条路! –

+1

查看我的答案,了解如何使用它的示例 – Alnitak

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 
}); 
相关问题