I have the following action:
$('.sub_outworker').live('click', function() {
var input = $(this);
var current_div = input.parents('div.report');
var current_div_id = current_div.attr('id');
var replace_div = current_div.children('div').first();
var submission = submit_form(input, replace_div);
var i = 0;
}
The submit_form() function looks like this:
function submit_form(input, replace_div) {
var form = input.parents('form');
loading_gif(replace_div);
$.ajax({
type: 'POST',
url: form.attr('action'),
data: 'ajax=true&' + form.serialize(),
success: function(data) {
get_json();
if(data == 'success') {
return 'success';
}
else {
return 'failed';
}
}
});
}
I want to check whether submission == failed and if it does run submit_form again (ie. give the function a second chance to work - mainly because it occasionally fails validation due to a mismatch in tokens). I'm not sure how to go about this though!
3 Answers 3
If you just want to run it one more time, the easiest (and IMO cleanest) way might be to use deferred objects [docs]:
function submit_form(input, replace_div) {
var deferred = new $.Deferred();
var form = input.parents('form');
loading_gif(replace_div);
$.ajax({
type: 'POST',
url: form.attr('action'),
data: 'ajax=true&' + form.serialize(),
success: function(data) {
get_json();
if(data == 'success') {
deferred.resolve(data);
}
else {
deferred.reject(data);
}
}
});
return deferred;
}
Then you can do:
var request = submit_form(input, replace_div);
request.fail(function() {
submit_form(input, replace_div);
}).done(function() {
// request was successful, do something
});
Deferred objects provide great flexibility with asynchronous calls and let you easily decouple code. Of course if you want to see the repeated attempt to make the Ajax call as a "feature" of the submit_form function or if you want to repeat it more than once, then @Matt's answer seems to be the better way.
Comments
It has to be done in the $.ajax() callback.
$('.sub_outworker').live('click', function() {
var input = $(this);
var current_div = input.parents('div.report');
var current_div_id = current_div.attr('id');
var replace_div = current_div.children('div').first();
submit_form(input, replace_div);
}
function submit_form(input, replace_div) {
var form = input.parents('form');
loading_gif(replace_div);
$.ajax({
type: 'POST',
url: form.attr('action'),
data: 'ajax=true&' + form.serialize(),
success: function(data) {
get_json();
if(data == 'success') {
submit_form.failCount = 0;
}
else if (!submit_form.failCount) {
submit_form.failCount++;
submit_form(input, replace_div);
}
}
});
}
5 Comments
$.ajax but that would only fail if the request itself fails, not when you just get a different value than success. You can still use your own deferred object though. See my updated answer.Could you do something like this? Note, I'm not 100% sure what you're expecting to get back from the server, or exactly how your page is structured.
function submit_form_ajax(serializedData, numAttempts) {
numAttempts--;
$.ajax({
type: 'POST',
url: form.attr('action'),
data: 'ajax=true&' + serializedData,
success: function(data) {
get_json();
if(data !== 'success') {
if( numAttempts >= 1 ) {
submit_form_ajax(serializedData, numAttempts-1);
}
}
}
});
}
function submit_form(input, replace_div) {
var form = input.parents('form');
loading_gif(replace_div);
submit_form_ajax(form.serialize(), 2);
}
successcallback.submit_formdoes not return anything.