views:

1441

answers:

5

Hi

I'm not massively experienced with JavaScript and I'm having trouble with variable scope and jquery. I have the following structure:

function pass_variables()
{
    username = "efcjoe"
    response = post_variables(username)
    alert(response)
}

function post_variables(username)
{
    $.post(
        '/path/to/url/',
        {
            'username': username,
        },
        function(data)
        {
            valid = (data != 0) ? true : false

            // OPTION 1: If I put return here...
            return valid; // ... the alert box in pass_variables says "undefined"
        },
        "text"
    );

    // OPTION 2: If I put return here...
    return valid; // ... The alert box does not pop up, and Safari debug gives
                  //     me the error: "Can't find variable: valid"
}

Am I missing something there? I think valid should be a global variable, and therefore option 2 should work fine. I'm really not sure about option 1.

Can anyone give me any advice on the best way to get this working?

Thanks a lot.

+6  A: 

Ajax calls are asynchronous which means they get called but do wait around for execution to complete. Basically your alert is firing before the ajax request has completed and run the callback function to change your variable.

The best thing you can do is actually pass a function to run when the ajax request has completed. This also negates the need for global variables which are frowned upon since other plugins, script can alter their state and leave your script open to errors, flaws etc

E.g

function foobar(){

   //call function to do post request and also pass a function to run
   //when post has returned
   runPostRequest( callbackFn );

}

function runPostRequest(callback){

    $.post( '/foo', callback );

}

function callbackFn( data ){

   console.log('post request complete');

}
redsquare
+3  A: 

Yeah, your problem is that you're not grasping some order of operations issues here. The function you're passing to $.post is a callback; it runs later, considerably after post_variables() finishes. post_variables() itself does not wait for the $.post to finish, so valid doesn't exist when you're trying to use it.

chaos
+2  A: 

Remember that AJAX is asynchronous. The return valid; gets executed immediately after the $.post() is set up, but before the post has completed (and therefore, before valid is defined). What you probably want to do is this:

function post_variables(username)
{
    var username = "efcjoe";

    $.post(
        '/path/to/url/',
        {
            'username': username,
        },
        function(data)
        {
            var valid = (data != 0) ? true : false
            alert(valid);
        },
        "text"
    );
}

And note that this no longer needs global variables, but function-scope variables that are declared using var.

Nate
+1  A: 

You could solve the problem quite easily by assigning it a function instead of an inline one, and the event function does the alert:

function pass_variables()
{
    username = "efcjoe"
    response = post_variables(username);
}

function post_variables(username)
{
    $.post(
        '/path/to/url/',
        {
            'username': username,
        },
        receivedData,
        "text"
    );
}

function receivedData(data)
{
    valid = (data != 0) ? true : false;
    alert(valid)
}
Chris S
+1  A: 

In your option 1 you are returning from the callback function, and its return value is never used because this function is only called when the Ajax request ends.

In the option 2, you are returning from your main function, but that return happens before the callback function assign any value to your valid variable.

I would refactor your code in this way, without using global variables:

function post_variables(username){
  $.post('/path/to/url/',{
    'username': username,
  },
  function(data){
    var valid = data != 0;

    // OPTION 3: Work in the callback function
    alert(username);
    alert(valid);

    // OPTION 4: Pass the values and work on another function
    otherFunction(username, valid);
  },"text");
}

function otherFunction(username, isValid){
  //...
}
CMS