2

I looked at this: Returning values from nested functions in Javascript

but it did not really help me (or I am just too dumb to get it).

My variable scope is somehow off and I don't understand why. My alert() does not behave as expected. Tried to add comments on all lines to explain what I'm thinking.

Thanks very much for any comments/pointers/answers!

var g = {}; / is a large object with all kinds of other stuff and functions in it

g.ding = function(){ // my problem function
 var baby = 'young'; // i thought I set a local var here
    if(someVar==true) { // standard issue if statement
        someAPI.class( // using an API that uses a function as its attribute
            function(stuff){ // my anonymous function
                baby = 'old'; // setting the var to something
            }
        );
    }
    return baby; // returning the var
}

alert( g.ding() ); // i expect it to say "old" but it keeps saying "young". why?

NEW EDIT: Juan's accepted answer is great, but isn't there also a way to use setTimeout() to deal with asynchronous function calls and essentially making them synchronous? if anyone who reads this knows the answer I'd love to know. Thanks.

Community
  • 1
  • 1
tim
  • 3,823
  • 5
  • 34
  • 39
  • Most likely, because `function(stuff)` is never being run. Your scoping looks fine. Nothing here proves that the line of code that sets `baby="old"` is ever executed. `someVar` could be false, or `someAPI` could never call the function you pass it. – Jamie Treworgy Jun 22 '12 at 04:29
  • well, I originally did check with an alert() that this function is being called. I think the async element of the API function is the solution. – tim Jun 22 '12 at 05:35

2 Answers2

7

The call to someAPI.class(function(){}) is probably asynchronous, that means the function you pass into it may not have been called when someAPI.class() returns and the variable hasn't been changed.

The solution is to pass the variable back in a callback

g.ding = function(callback){ 
    var baby = 'young';
    if(someVar) {
        someAPI.class(
            // There's no guarantee of when this function is called
            function(stuff){
                baby = 'old';
                // Call the callback, it's like a return, for async functions
                callback(baby);
            }
        );
    }
    // the inner function probably wasn't called yet, 
    // doesn't make sense to return this here
    // return baby;
}

// Then you'd call it like this, as soon as you use an async function
// all the functions that call it have to use callbacks for return values
g.ding(function(value){
    alert(value);
});
Ruan Mendes
  • 90,375
  • 31
  • 153
  • 217
  • thanks a bunch Juan, this definitely made it clear for me. Always struggle with async. – tim Jun 22 '12 at 06:08
  • @tim BTW, `class` is a reserved keyword and should not be used as a property name (unless you always use it with `someAPI["class"]()` I'm hoping that's not the real name of the method you're calling – Ruan Mendes Jun 22 '12 at 17:09
  • Juan, thanks yes I know that about 'class' - I was simplifying the code sample for clarity's sake. – tim Jun 25 '12 at 17:02
0

Here I can think that your

 someAPI.class();

must be an event related function (like click, mouseover etc.). So the function inside it will be performed only when the related event occurs and hence change the value of the variable. But I think the event does not occur and hence the variable will not change.

me_digvijay
  • 5,374
  • 9
  • 46
  • 83