1

I am using the following code to show value return by the function test2.

The output showing is: Value of x is: undefined

Can anyone help me in explaining how can I return a value from function test2? Please note that the function test2 is XMLHTTPRequest

<script language="javascript">

    function test1()
    {
        var x = test2();
        alert('Value of x is: '+x);
    }

    function test2()
    {
        if(window.XMLHttpRequest)
        {
            abcd= new XMLHttpRequest();
        }
        else
        {
            abcd=new ActiveXObject("Microsoft.XMLHTTP");
        }

        abcd.onreadystatechange=function()
        {
            if (abcd.readyState==4 && abcd.status==200)
            {
                    return abcd.responseText; // it is getting value 2 here
            }
            else if(abcd.readyState < 4)
            {
                return -1;
            }
        }
        abcd.open("GET",sam.php,true);
        abcd.send();
    }

</script>
sumit
  • 10,935
  • 24
  • 65
  • 83
  • 1
    possible duplicate of [Return value from function with an Ajax call](http://stackoverflow.com/questions/562412/return-value-from-function-with-an-ajax-call) – Felix Kling Aug 10 '11 at 22:12
  • The trouble here is that AJAX is by asynchronous. And your code assumes that when the function test2() returns data is available. This may not be the case which is why a callback function is needed which will be called on successful completion of the ajax call. – Ali Aug 10 '11 at 22:14
  • Hi Ali - Thanks for the comment. I know tons are available. I am asking about a concept (async / sync) here not the code! :) – sumit Aug 10 '11 at 22:16

5 Answers5

8

It sounds like you want the value from the XML HTTP request to be the return of test2. This is simply not possible as this XML HTTP request executes asynchronously and test2 executes synchronously.

The proper way to handle this is to pass a callback to test2 to execute at the completion of the request. The callback is provided the value which is returned from the XML HTTP request. For example

function test1() {
  test2(function (x) {
    alert('The value of x is ' + x);
  });
}

function test2(callback) {
  ...
  abcd.onreadystatechange=function() {
    if (abcd.readyState==4 && abcd.status==200) {
      callback(abcd.responseText);
    } else {
      callback(-1);
    }
  }
  ...
}
JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454
  • "XML HTTP request executes asynchronously" is not always true. See last parameter of `XMLHttpRequest.open()`. – c-smile Aug 10 '11 at 22:13
  • @c-smile: Well, by default it does. And making synchronous requests is a bad idea. It may freeze the browser (the user will notice if the the whole process takes longer than 100ms). – Felix Kling Aug 10 '11 at 22:15
  • @c-smile i intended for that to mean "this particular XML HTTP request" vs. all of them. I'll try to make that clearer – JaredPar Aug 10 '11 at 22:16
3

The function test2 returns immediately (the value undefined). You need to wait for your AJAX call to return before you try to get any data from it. That's the (A)synchronous part of AJAX.

abcd.onreadystatechange=function()
{
    if (abcd.readyState==4 && abcd.status==200)
    {
        // Put the code that deals with the returned value here...
    }
    else if(abcd.readyState < 4)
    {
        return -1;
    }
}
FishBasketGordo
  • 22,904
  • 4
  • 58
  • 91
  • So should I change `abcd.open("GET",sam.php,true);` to `abcd.open("GET",sam.php,false);` ? – sumit Aug 10 '11 at 22:09
  • See my edit. It's been a while since I've done any raw AJAX like this, but I think I'm steering you in the right direction. – FishBasketGordo Aug 10 '11 at 22:12
  • If you choose to make your XHR synchronous, it'll block your UI until the XHR is finished, it's a really bad choice. You just need to realize that you can't return a value from a function that makes asynchronous requests. Your test2 function needs to accept a callback function that you can call after the XHR finished. you call it passing whatever you would have returned in a synchronous case. – Ruan Mendes Aug 10 '11 at 22:14
1

As expected, the function test1 calls test2, which makes the XMLHttpRequest. But the problem here is with your timing. The onreadystatechange is called only when the state changes. By the time the state changes, the function test2 has already exited without a return value.

Instead, your alert should happen where you currently have return abcd.responseText.

Jared Ng
  • 4,891
  • 2
  • 19
  • 18
1

The function test2 is not returning anything but the callback you assigned to onreadystate change is. You should call test1 from this callback and pass the value of x into it like so:

function test1(x)
{
    alert("X is: " + x);
}

function test2()
{
    // ...
    abcd.onreadystatechange=function()
    {
        var x = -1;
        if (abcd.readyState==4 && abcd.status==200)
        {
                x = abcd.responseText; // it is getting value 2 here
        }
        test1(x); // call test1 and pass in x
    }
    / ...
}
Daveo
  • 1,155
  • 2
  • 8
  • 16
1

You cannot do it that way, your ajax request is asynchronus. So when you are executing test2() you are not getting any value.

Be aware that defining a onreadystate function, it gets various responses from server, thats why you are validating the readystate 4 and statuscode 200, you will get into that function various times. When the server finish it returns those codes if everything went fine.

You should do it like this way:

<script language="javascript">

    function test1()
    {
        var x = test2();       
    }

    function test2()
    {
        if(window.XMLHttpRequest)
        {
            abcd= new XMLHttpRequest();
        }
        else
        {
            abcd=new ActiveXObject("Microsoft.XMLHTTP");
        }

        abcd.onreadystatechange= test2Result;
        abcd.open("GET",sam.php,true);
        abcd.send();
    }

    function test2Result()
    {
            if (abcd.readyState==4)
            {
                 if(abcd.status==200)
                 {
                    alert(abcd.responseText); // it is getting value 2 here
                 }
                 else 
                 {
                    alert('Something failed');
                 }
            } 

    }

</script>
Hector Sanchez
  • 2,297
  • 4
  • 26
  • 39