Web Developer Web Developer - 5 months ago 37
jQuery Question

Ajax Request Wait Until First AJAX Call not complete

I have below code for auto saving but i have problem lot of Ajax request firing on same time, i want to wait Ajax request Until first Ajax request not complete

window.submitting = false;
$('form#AddForm').submit(function() {
window.submitting = true;
});

var timeoutId;
$('form input, form textarea, form select').bind('input propertychange change', function() {
console.log('Change');

if (window.submitting)
return false;

clearTimeout(timeoutId);
timeoutId = setTimeout(function() {
// Runs 5 second (5000 ms)
autoSave();
}, 5000);
});

function autoSave() {
$.ajax({
type: "POST",
data: $('form#AddForm').serialize() + '&autosave=true',
beforeSend: function(xhr) {
// Let them know we are saving
console.log('Saving........');
},
success: function(data) {
var jqObj = jQuery(data); // Ajax call here.
var ProductId = jqObj.find("#ProductId").val();
var url = $(location).attr('href');
var split = url.split("add");
if (ProductId) {
history.pushState({}, null, split[0] + "add/" + ProductId);
$('#ProductId').val(ProductId);
$('form#AddForm').attr('action', '/dataproducts/add/' + ProductId);
}
},
});
}

Answer

It looks like i've catch your problem. If user triggers few change events on form elements new ajax request would be created, but shouldn't until previous are in process.

My guess you can use next approach: unbind listeners from form elements before you send ajax and bind them back when ajax would be completed.

There are an excellent answer on SO regarding binding/unbinding: Best way to remove an event handler in jQuery?

So basically you have to make a litle refactoring and add few lines of code:

window.submitting = false;
$('form#ProductAddForm').submit(function() {
    window.submitting = true;
});

var timeoutId;
var saveHandler = function() {
    console.log('Change');

    if (window.submitting)
        return false;

    clearTimeout(timeoutId);
    timeoutId = setTimeout(function() {
        // Runs 5 second (5000 ms)
        autoSave();
    }, 5000);
};

$('form input, form textarea, form select').bind('input propertychange change', saveHandler);

function autoSave() {
    // unbind events
    $('form input, form textarea, form select').unbind('input propertychange change')
    $.ajax({
        type: "POST",
        data: $('form#ProductAddForm').serialize() + '&autosave=true',
        beforeSend: function(xhr) {
            // Let them know we are saving
            console.log('Saving........');
        },
        success: function(data) {
            var jqObj = jQuery(data); // Ajax call here.
            var ProductId = jqObj.find("#ProductId").val();
            var url = $(location).attr('href');
            var split = url.split("add");
            if (ProductId) {
                history.pushState({}, null, split[0] + "add/" + ProductId);
                $('#ProductId').val(ProductId);
                $('form#ProductAddForm').attr('action', '/account/products/add/' + ProductId);
            }
            // bind events back
            $('form input, form textarea, form select').bind('input propertychange change', saveHandler);
        },
        error: function{
            // bind events back even if reqeust fail
            $('form input, form textarea, form select').bind('input propertychange change', saveHandler);
        }
    });
}

Note jqXHR.success and jqXHR.error is deprecated, see $.ajax for more info. Also i've added error method, because you cannot miss binding listeners if ajax fails ...

Comments