variable not writable in inner function

$(document).ready(function() {
    state = 0;
    $('#btnlogin').click(function() {
        $.post("php/redirect.php", {
            Username : $('#qi').attr('value'),
            Password : $('#password').attr('value')
            }, function(data) {
            console.log('first'+state);
            state = 3;
            console.log('second'+state);
        });
        console.log('third'+state);
    });
});

First I have declared a global variable and set it to 0.

In the inner function I want to set the var to another value, but my output wont set in the (global)outer var, it will be set just as a local var. My other problem is the order in wich I get the output.

Output:

  • TypeError in Javascript console
  • Inspect the HTML Element Which comes only on Hover or Focus
  • firebug: how to break on any javascript activity?
  • Why is Firebug hitting non-existent break points?
  • Firebug finds error which does not exist
  • Why is Firefox 3 breaking with console.log
  • third0<br>
    first0<br>
    second3<br>
    

  • Javascript debugging: stopping/breaking at every javascript invocation
  • Cross browser console.log for greasemonkey/chrome userscripts
  • How to debug in Firebug when code is in separate JS file?
  • How can I set breakpoints in an external JS script in Firebug
  • Monitor JavaScript events
  • How to edit JavaScript in Firebug?
  • 3 Solutions collect form web for “variable not writable in inner function”

    It happens because console.log('third'+state); is outside $.post (AJAX) call and calls faster than ajax response.

    Seems that you misunderstood that AJAX is asynchronous.

    You problem is that the inner function on the $.post call will be run first when the post call returns from the server.

    So you program flow will go like this when the button is clicked:

    $.post("php/redirect.php", this will call the redirect.php method on the server side, and the up the following function to be called when the call is complete:

    function(data) {
      console.log('first'+state);
      state = 3;
      console.log('second'+state);
    }
    

    Then the function continues and runs the following code:

    console.log('third'+state);
    

    At this point, state is still 0, so the output is third0.

    Then the ajax call completes, and calls you function above, and thereby prints the following:

    first0
    second3
    

    You problem is simply expecting the lines in your method, including the function you define inside to be run in the same order they appear in your script.

    The output is really simple to explain:

    After the document has loaded you start by binding a click handler to some button. The click handler works in the following way:

    • Starting an asynchronous AJAX call
    • logging out 'third'+state

    At that point state is 0, so the first output is third0.

    After some time the AJAX request succeded and you got your answer. When getting the answer you log 'first'+state. With state still being 0 you get the output first0.

    Afterwards you change the value of state to three and to the third output, which gets you the second3.

    So to understand the behaviour you should familiarize yourself with the asynchronous version of AJAX or change the request to a synchronous style. The later is quite bad, as it would render your page unaccessible while the request is still running.