0

Ok,I've been trying to get this to work for the past two days and I cannot figure out what I am doing wrong. I have a function called "ping" that makes a calculation, and I have a callback function to retrieve the calculated value, but all I keep getting is undefined!

var test;

var p = ping('apple.com', function (num) {
    test = num;
    console.log(test); //this works, the value is displayed in the console.
}); 

console.log("p: " +p); //says undefined
console.log("test: " +test); //says undefined

Can someone tell me what I am doing wrong? Thanks!

Edit: Here is the ping function:

function ping(host, pong) {

  var started = new Date().getTime();

  var http = new XMLHttpRequest();

  http.open("GET", "http://" + host, /*async*/true);
  http.onreadystatechange = function() {
    if (http.readyState == 4) {
      var ended = new Date().getTime();

      var milliseconds = ended - started;

      if (pong != null) {
        pong(milliseconds);
        //console.log(milliseconds);
        return milliseconds;
      }
    }
  };
  try {
    http.send(null);
  } catch(exception) {
    // this is expected
  }

}
twkl
  • 11
  • 4

2 Answers2

2

ping is an asynchronous function - this means that the callback function is executed "at some point later".

var test;    
ping('apple.com', function (num) {
    // this is called "at some point later" ..
    test = num;
    console.log(test);
}); 
// .. but this executes IMMEDIATELY after the ping(..) function is called ..
// .. which is before the callback (and thus assignment to `test`)
console.log("test: " +test);

The solution is to only continue work as a result of the callback event. This can be hidden in different ways - e.g. callbacks, promises, and futures/observables - but it's always the same process.

ping(..) also returns undefined (or rather, it doesn't return at all), which explains why p is undefined - but that's secondary and has nothing to do with the asynchronous nature.


See How do I return the response from an asynchronous call?

Community
  • 1
  • 1
user2864740
  • 60,010
  • 15
  • 145
  • 220
-1

You could use synchronous AJAX.

function ping(host,pong){
    var http = new XMLHttpRequest();

    http.open("GET", "http://" + host, /*not async*/false);
    http.send(null);

    if(pong)pong(http.responseText);
    return http.responseText;
};

Otherwise you will not be able to return the http.responseText.

However, this technique is not really best practice because it causes all other Javascript on the page to stall until the request has completed. If the server takes a long time to answer, then your page will be not responding. Extremely annoying to users.

Note that you would have an error trying to do AJAX to another domain as you have shown in the code in your question.

Robbie Wxyz
  • 7,671
  • 2
  • 32
  • 47