Я некоторое время назад такой скрипт для использовал:
$('form.async').submit(function(e){
e.preventDefault();
var $form=$(this),
$this=$form.find('[type="submit"]'),
invalid_class='invalid';
if($form.find('[name][required]').removeClass(invalid_class).filter(function(){
return !this.value.trim().length;
}).addClass(invalid_class).first().each(function(){
this.focus();
}).length || $this.attr('disabled')!==undefined)
return;
$this.attr('disabled',true);
var method=($form.attr('method')||'post').toLowerCase(),
is_formdata=(!!window.FormData && method=='post' && $form.find('[type="file"]').length),
xhr_params=$.extend({},{
url:$form.attr('action'),
method:method,
data:is_formdata?(new FormData($form.get(0))):$form.serialize(),
error:function(xhr,text_status,text_error){
//тут обработчик ошибки
},
success:function(res,xhr,text_status){
//тут обработчик успешного окончания запроса
},
complete:function(xhr,text_status){
$this.removeAttr('disabled');
}
},is_formdata?{
contentType:false,
processData:false
}:{});
$.ajax(xhr_params);
});