Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Need help with variable scope in Javascript

I have the following Javascript function that should return an array of groups that are in database. It uses $.getJSON() method to call get_groups.php which actually reads from the database.

function get_groups() {
    var groups = [];

    $.getJSON('get_groups.php', function(response) {
        for (var i in response) {
            groups.push(response[i]);
        }
    }

    return groups;
}

Unfortunately, this function does not work as expected because groups.push(response[i]); does not fill the var groups = []; (as I understand it fills some other groups array, probably the global one).

Assuming that I don't want to have a global groups variable, how would you solve this problem ?

like image 974
Misha Moroshko Avatar asked Aug 17 '10 10:08

Misha Moroshko


People also ask

What are the scope of variable in JavaScript?

JavaScript variables have only two scopes. Global Variables − A global variable has global scope which means it can be defined anywhere in your JavaScript code. Local Variables − A local variable will be visible only within a function where it is defined. Function parameters are always local to that function.

How do you use scope in JavaScript?

In JavaScript, scopes are created by code blocks, functions, modules. While const and let variables are scoped by code blocks, functions or modules, var variables are scoped only by functions or modules. Scopes can be nested. Inside an inner scope you can access the variables of an outer scope.

What are the 4 different types of scopes that a variable can have?

Local Scope, Global Scope, Enclosed Scope, and Built-in Scope. Local Scope: Local scope refers to variables defined in the current function. Always, a function will the first lookup for a variable name in its local scope.

What are the 4 ways to declare a JavaScript variable?

4 Ways to Declare a JavaScript Variable:Using var. Using let. Using const. Using nothing.


2 Answers

It's not a scope issue really, it's the fact that $.getJSON() is asynchronous, meaning that this part runs after you return:

for (var i in response) {
  groups.push(response[i]);
}

You need to call whatever function needs this data in the callback of the asynchronous request, so it runs when the data's available, like this:

$.getJSON('get_groups.php', function(response) {
    var groups = [];
    for (var i in response) {
        groups.push(response[i]);
    }
    doSomethingThatNeedsGroups(groups);
});

Currently you groups array is getting populated, just not when you need it to. If you absolutely have to return this (I strongly recommend using the asynchronous model the way it was intended) you can use the full $.ajax() version and set async:false. Again...don't go that route if possible, stick to calling whatever function needs the data once it's available, as async: false will lock up the user's browser.

like image 200
Nick Craver Avatar answered Oct 24 '22 00:10

Nick Craver


Unless you really have a global variable with the name groups (which would be not the best idea actually), you are talking to your "local" groups variable.

Since EMCA-/Javascript does have function scope and you are using a closure there, you do have access to that variable. So the problem here, is not the scope. So even with a global variable with the exact same name, the such called lexical scope will guarantee you the access to your local variable.

The actuall problem is, that return groups is executed before $.getJSON() does complete. Since it creates an ajax request, it run asynch.

You should use a callback yourself to process the data:

function get_groups(cb) {
   var groups = [];

   $.getJSON('get_groups.php', function(response) {
       for (var i in response) {
           groups.push(response[i]);
       }
       cb.apply(null, [groups]);
   }
}

get_groups(function(groups){
   // do something with groups array
});
like image 39
jAndy Avatar answered Oct 24 '22 00:10

jAndy