Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I wait for a .each loop that makes async calls?

I have some javascript code that updates some data to a database using a http handler, but this async call is made inside an .each loop. At the end of the loop I make a call to function CancelChanges() that refreshed the page. The problem is that the page seems to refresh before the database is updated. The .each loop seems to finish after the call to CancelChanges(). How can I make sure the page is refreshed after all the async calls are completed in the .each loop?

function SaveChanges() {
    if (PreSaveValidation()) {
        var allChangesSucceeded = true;
        var studioId = $("#param_studio_id").val();
        var baseDate = $("#param_selected_month").val().substring(6, 10) + $("#param_selected_month").val().substring(0,2);
        var currency = "CAD";
        var vacationPct = null;
        var gvAdmissible = null;

        $(".editable-unsaved").each( function() {
            var newSalary = $(this).text();
            var disciplineId = $(this).data("disciplineid");
            var seniorityId = $(this).data("seniorityid");
            var handlerCommand = "";
            if ($(this).data("valuetype") === "inflated") {
                handlerCommand = "AddAverageSalary";
            } else if ($(this).data("valuetype") === "actual") {
                handlerCommand = "UpdateAverageSalary";
            }
            $.get("WS/AverageSalary.ashx", { command: handlerCommand, studio_id: studioId, discipline_id: disciplineId, seniority_id: seniorityId, base_date: baseDate, currency: currency, salary: newSalary, vacation_pct: vacationPct, gv_admissible: gvAdmissible }).done(function (data) {
                if (data != "1") {
                    $(this).removeClass("editable-unsaved");
                    allChangesSucceeded = true;
                }
                else {
                    alert('fail');
                    allChangesSucceeded = false;
                }
            });
        });
        if(allChangesSucceeded) CancelChanges();
    }
}

function CancelChanges() {
    var href = window.location.href;
    href = href.split('#')[0];
    window.location.href = href;
}
like image 207
Ray Avatar asked Jan 09 '23 13:01

Ray


2 Answers

You could try using Promises and jQuery $.when

Store a list of the ajax call promises:

var defereds = [];

$(".editable-unsaved").each( function() {
    //...
    defereds.push($.get("WS/AverageSalary.ashx" /*...*/));
}
$.when.apply($, defereds).done(function() {
    CancelChanges();
});

This should, hopefully, wait for all the ajax calls to finish before calling CancelChanges()

like image 130
lemieuxster Avatar answered Jan 11 '23 01:01

lemieuxster


I think you need to change your structure a little bit, using a counter and calling CancelChanges when the counter equals the number of calls.

function SaveChanges() {
    if (PreSaveValidation()) {
        var studioId = $("#param_studio_id").val();
        var baseDate = $("#param_selected_month").val().substring(6, 10) + $("#param_selected_month").val().substring(0,2);
        var currency = "CAD";
        var vacationPct = null;
        var gvAdmissible = null;

        var editableUnsaveds = $(".editable-unsaved"); //cache the selector here, because selectors are costly
        var numOfGetsReturned = 0;            

        editableUnsaveds.each( function() {
            var newSalary = $(this).text();
            var disciplineId = $(this).data("disciplineid");
            var seniorityId = $(this).data("seniorityid");
            var handlerCommand = "";
            if ($(this).data("valuetype") === "inflated") {
                handlerCommand = "AddAverageSalary";
            } else if ($(this).data("valuetype") === "actual") {
                handlerCommand = "UpdateAverageSalary";
            }
            $.get("WS/AverageSalary.ashx", { command: handlerCommand, studio_id: studioId, discipline_id: disciplineId, seniority_id: seniorityId, base_date: baseDate, currency: currency, salary: newSalary, vacation_pct: vacationPct, gv_admissible: gvAdmissible }).done(function (data) {
                if (data != "1") {
                    $(this).removeClass("editable-unsaved");
                }
                else {
                    alert('fail');
                }
                if(editableUnsaveds.length === ++numOfGetsReturned){
                   CancelChanges(); //now it should call when the final get call finishes.
                }
            });
        });
    }
}

function CancelChanges() {
    var href = window.location.href;
    href = href.split('#')[0];
    window.location.href = href;
}
like image 24
James G. Avatar answered Jan 11 '23 02:01

James G.