0

I have some problems with returning a value from a function into a variable. It is apparently "undefined". This apparently happens due to the asynchronity of JavaScript. But in my case I don't know how to circumvent it with "callbacks" or "promises". Please see code below. I would like to return the exchange rate saved in "value" back to "rate" and use it further in my code. Any ideas?

var rate = rateCalc();
var currency = "EUR";
 
function rateCalc(){
 var value;
 if (currency != "EUR") {
  var xmlhttp = new XMLHttpRequest();
  var rateURL = "http://query.yahooapis.com/v1/public/yql?q=select%20rate%2Cname%20from%20csv%20where%20url%3D'http%3A%2F%2Fdownload.finance.yahoo.com%2Fd%2Fquotes%3Fs%3D"+"EUR"+"HKD"+"%253DX%26f%3Dl1n'%20and%20columns%3D'rate%2Cname'&format=json";
  xmlhttp.onreadystatechange = function() {
   if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
    var json = JSON.parse(xmlhttp.responseText);
    value = json.query.results.row.rate;
    alert("At this position the value is defined: "+ value);
    return value;
   }
  }
 xmlhttp.open("GET", rateURL, true);
 xmlhttp.send();
 }
 
 else {
  value = 1;
  return value;
 }
}
alert("The return statement somehow didn't work: "+ rate);

I'm a newbie, by the way. So sorry, if this question has already been asked like a million times before.

Thanks René

René K
  • 337
  • 5
  • 14
  • You can't do that. http://blog.slaks.net/2015-01-04/async-method-patterns/ – SLaks Aug 25 '15 at 14:19
  • possible duplicate of [How to return the response from an asynchronous call?](http://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-asynchronous-call) – Paul Roub Aug 25 '15 at 15:36

4 Answers4

1

You can't return anything from a async function in JS. So create a new function and use it as a callback function. See the below example.

    var rate = rateCalc();
    var currency = "EUR";

    function rateCalc(){
        var value;
        if (currency != "EUR")  {
            var xmlhttp = new XMLHttpRequest();
            var rateURL = "http://query.yahooapis.com/v1/public/yql?q=select%20rate%2Cname%20from%20csv%20where%20url%3D'http%3A%2F%2Fdownload.finance.yahoo.com%2Fd%2Fquotes%3Fs%3D"+"EUR"+"HKD"+"%253DX%26f%3Dl1n'%20and%20columns%3D'rate%2Cname'&format=json";
            xmlhttp.onreadystatechange = function() {
                if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
                    var json = JSON.parse(xmlhttp.responseText);
                    value = json.query.results.row.rate;
                    alert("At this position the value is defined: "+ value);
                    valueCallBack(value); //Callback function

                }
            }
        xmlhttp.open("GET", rateURL, true);
        xmlhttp.send();
        }

        else {
            value = 1;
            return value;
        }
    }

   function valueCallBack(value){

     console.log("value is " + value);      
   } 

Update : You can use the Promise API introduced in the ES6 or use JQUERY deferred objects.

Jijo John
  • 1,375
  • 9
  • 21
  • Hello Jijo John and @nx0side, thanks for your replies. I guess you mean the same thing. That means all further calculations have to be done within the callback function, right? Because outside of it the variable is not recognized again. – René K Aug 25 '15 at 15:06
0

xmlhttp.send() shouldn't be empty. Try this. I hope it will do the job!

xmlhttp.send(null);
0

You can send the response value to another function so when you have a value it will be displayed without it being undefined.

Try this:

rateCalc();
var currency = "EUR";

function rateCalc() {
    var value;

    if (currency != "EUR")  {
        var xmlhttp = new XMLHttpRequest();
        var rateURL = "http://query.yahooapis.com/v1/public/yql?q=select%20rate%2Cname%20from%20csv%20where%20url%3D'http%3A%2F%2Fdownload.finance.yahoo.com%2Fd%2Fquotes%3Fs%3D"+"EUR"+"HKD"+"%253DX%26f%3Dl1n'%20and%20columns%3D'rate%2Cname'&format=json";

        xmlhttp.onreadystatechange = function() {
            if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
                var json = JSON.parse(xmlhttp.responseText);
                value = json.query.results.row.rate;
                show(value);
            }
        };

        xmlhttp.open("GET", rateURL, true);
        xmlhttp.send();
    } else {
        value = 1;
        show(value);
    }
}

function show(rate) {
    alert("Value: "+ rate);
}
  • @René: To the comment in Jijo post: Yes, you need to operate inside of the callback function. –  Aug 25 '15 at 15:19
0

So this is how I changed the code now. The call back function is used for all further calculations with the called back value. Thanks again to @Jijo John and @nx0side.

var currency = "HKD";
var value;
  
if (currency != "EUR")
 {
  var xmlhttp = new XMLHttpRequest();
  var rateURL = "http://query.yahooapis.com/v1/public/yql?q=select%20rate%2Cname%20from%20csv%20where%20url%3D'http%3A%2F%2Fdownload.finance.yahoo.com%2Fd%2Fquotes%3Fs%3D"+"EUR"+"HKD"+"%253DX%26f%3Dl1n'%20and%20columns%3D'rate%2Cname'&format=json";
  xmlhttp.onreadystatechange = function()
  {
  if (xmlhttp.readyState == 4 && xmlhttp.status == 200)
   {
    var json = JSON.parse(xmlhttp.responseText);
    value = json.query.results.row.rate;
    valueCallBack(value); //Callback function
   }
  }
  xmlhttp.open("GET", rateURL, true);
  xmlhttp.send();
 }
  
else
 {
  valueCallBack(1);
 }

//in this function all further calculations with "value" need to take place.
function valueCallBack(value)
{
 //example
 var result = 70000/value;
 console.log("Result is " + result);
}
René K
  • 337
  • 5
  • 14