F.Fasser F.Fasser - 6 months ago 7
Javascript Question

Why my JavaScript function is executing uncertainly if i add an alert()?

I wrote the function below to get the length of a

listbox
with the id
courselessons
. The problem is that when I comment the
alert()
the function
changecheckbox
works only once.

If I remove the
alert
it works fine. But I don't want to have an alert on every single click.

The
selOpts
shows correct content only for the first time.

JavaScript:



function changecheckbox() {
//alert("function called...");
var selOpts = document.getElementById("courselessons").length();
alert(selOpts);
if (selOpts > 0) {
$('#taskassignment').prop('disabled', false);
}
else {
$('#taskassignment').prop('disabled', true).prop("checked", false);
}
}

function addItem() {
if (seltask == undefined || seltask.length === 0) {
return;
}
var lessonsDropdown = $('#courselessons');
lessonsDropdown.empty();
$("#tasks option:selected").appendTo("#coursetasks");
$("#coursetasks option").attr("selected", false);
if (seltask.length > 0) {
cacheToken = new Date().getTime();
// retrieve data using a Url.Action() to construct url
$.getJSON('@Url.Action("AddTaskToCourse")', {
task: seltask,
lesson: lesson,
_: cacheToken
});
$.getJSON('@Url.Action("UpdateLessonInCourse")', {
_: cacheToken
}).done(function (data) {
//re-enable tasks drop down
//for each returned tasks
$.each(data, function (i, lessons) {
//Create new option
var test = $('<option />').html(lessons);
//append tasks taskss drop down
lessonsDropdown.append(test);
});
seltask = null;
});
}
changecheckbox();
}


HTML:



<button type="button" id="btnAdd" onclick="addItem(); changecheckbox();">Add Item</button>

Answer

The code inside addItem() is making a GET request to a resource asynchronously. This means the code which comes after this function to be execute will not wait for its execution to get complete.

When I uncomment the alert it works fine.

That is because as the alert() is built in, it halts the execution of script until user interaction. This gave the time addItem() needs and everything seems to work.

Fortunately, there are solutions available to handle this situation.

  1. Promise.
  2. Rearrange your code to work with callbacks.

Under the covers, $.getJSON is shorthand for making a GET request using ajax with datatype = 'json'and it returns a promise object which basically tells that please wait honey, i will give you something which could be a success or a failure but sometime later.

So yes, you can easily call the function inside the done().

NOTE: These things have been explained pretty well on web so i will not reinvent the wheel :)

Keeping the things simple...

function addItem() {

    // Rest of the code...

    if (seltask.length > 0) {
        cacheToken = new Date().getTime();
        // retrieve data using a Url.Action() to construct url
        $.getJSON('@Url.Action("AddTaskToCourse")', {
            task: seltask,
            lesson: lesson,
            _: cacheToken
        });
        $.getJSON('@Url.Action("UpdateLessonInCourse")', {
            _: cacheToken
        }).done(function (data) {
            //re-enable tasks drop down
            //for each returned tasks
            $.each(data, function (i, lessons) {
                //Create new option
                var test = $('<option />').html(lessons);
                //append tasks taskss drop down
                lessonsDropdown.append(test);
            });
            seltask = null;
            changecheckbox();
        });

    }        
}

After this setup, you should remove the changecheckbox() call from the button onclick otherwise it would make it execute twice.