views:

48

answers:

3

I'm caching label strings by saving them into a variable, but running into weird scoping issues. I know this has to do with closures, but I can't seem to figure out what the issue is exactly.

info_lbl = {};

$("#chkCorporateGift").click(function(){
    var type = $(this).is(":checked") ? "Corporate" : "Personal";
    if(!info_lbl.hasOwnProperty(type)){
        $.ajax({
            url: svc_og + "Get" + type + "InformationLabel",
            success: function(data){
                info_lbl[type] = data;
            }
        });
    }
    $("#lblInformationType").text(info_lbl[type]);
});

lblInformationType label isn't set the very first time GetCorporateInformationLabel or GetPersonalInformationLabel methods are called. After the first time each one is called, the label's value is being changed. Could somebody please explain why this behavior occurs? When I use Firebug and set a break point on $("#lblInformationType").text(info_lbl[type]);, info_lbl[type] contains the right value and everything works fine on the first two calls as well.

+5  A: 

AJAX calls are asynchronous. This means that any code following the request does not wait for the request to return before it runs.

In other words, the AJAX request does not block execution of subsequent lines of code. So by the time the response is received from the AJAX request, the following lines of code have already executed.

Any code that relies on the response of the AJAX request should be placed inside the callback.

$("#chkCorporateGift").click(function(){
 //   var type = $(this).is(":checked") ? "Corporate" : "Personal";
    // It is more efficient to use this.checked instead of using .is(":checked")
    var type = this.checked ? "Corporate" : "Personal";
    if(!info_lbl.hasOwnProperty(type)){
        $.ajax({
            url: svc_og + "Get" + type + "InformationLabel",
            success: function(data){
                info_lbl[type] = data;
                  // code that relies on the response needs to be placed in
                  //   a callback (or in a function that is called here).
                $("#lblInformationType").text(info_lbl[type]);
            }
        });
    } else {
        $("#lblInformationType").text(info_lbl[type]);
    }
});

I would image that the reason things work properly when you have a breakpoint is that the pause in execution gives the AJAX response time to return.


EDIT: Improved efficiency of the code by using this.checked instead of the original $(this).is(':checked').

patrick dw
Thank you so much for your explanation - this makes sense now. Why is this.checked more efficient, however?
alkos333
@alkos333 - You're welcome. :o) And `this.checked` is more efficient because you're directly reading the value of the `checked` property (which will be true/false) of the DOM element instead of having to create a jQuery object and run a `:checked` filter against the element, only to end up with the same result. Imagine if you had a local variable `myVar` that you knew was `true` or `false`. If you wanted to use the value of `myVar`, you would just ask for it. You wouldn't run some code that tests whether `myVar` was true or false, and return true or false based on the result of the test. :o)
patrick dw
+1  A: 

Move this line:

        $("#lblInformationType").text(info_lbl[type]);

into the "success" callback.

Pointy
+1  A: 

As said above, there is 2 solutions :

1) Making $.ajax asynchronous

$.ajax({
    url: svc_og + "Get" + type + "InformationLabel",
    async: false,
    success: function(data){
        info_lbl[type] = data;
    }
});

2) Keep it asynchronous but doing twice :

var type = $(this).is(":checked") ? "Corporate" : "Personal";
if(!info_lbl.hasOwnProperty(type)){
    $.ajax({
        url: svc_og + "Get" + type + "InformationLabel",
        success: function(data){
            info_lbl[type] = data;
            $("#lblInformationType").text(data);
        }
    });
}
$("#lblInformationType").text(info_lbl[type]);
Arnaud F.
Do you mean "making $.ajax synchronous" in solution 1?
SauceMaster