Skip to content Skip to sidebar Skip to footer

How Can I Get This JSONP Call To Return A Value?

The purpose of the following functions are to access a script on Yahoo's servers and lookup a live currency conversion rate which will later be used to process a customer's purchas

Solution 1:

the variable rate has not been defined

$(function() {

    getRate('USD', 'PHP');
    xRatePHP = rate;

    /* Do stuff with rate */

});

after studying your code it seems that rate is defined in the parseExchange(data) function as

function parseExchangeRate(data) {

    var name = data.query.results.row.name;
    rate = parseFloat(data.query.results.row.rate, 10);

    alert("Exchange rate " + name + " is " + rate);

}

if you want rate to be accessible from the function namespaces without declaring them from within then the rates would have to specified in the global namespace, which is outside any of the functions or loops.

Edit: The namespace problem has been solved and the answer I've given has been accepted, however I would like to add details about the code you are handling here. It has been taken from the gist here: https://gist.github.com/henrik/265014

We are dealing with JSONP here

the reason why parseExchangeRate exists and the context of it can seem mysterious at first glance, albeit its existence is the primary connection between your JSONP request and the data returned by the response.

If you take a closer look at the request:

http://query.yahooapis.com/v1/public/yql?
q=select%20rate%2Cname%20from%20csv%20where%20url%3D'http%3A%2F%2F
download.finance.yahoo.com%2Fd%2F
quotes%3Fs%3DUSDPHP%253DX%26f%3Dl1n'%20and%20
columns%3D'rate%2Cname'&format=json&callback=parseExchangeRate

(I broke the link up into many lines to make it easier to read)
Carefully look at the last segment of the url: callback=parseExchangeRate
This here is the connection, when the JSONP request is complete parseExchangeRate will be called.

So then why did it not work?

Let me display the code once again:

$(function() {

    getRate('USD', 'PHP');
    xRatePHP = rate;

    /* Do stuff with rate */

});

We should break this up:

  • getRate('USD', 'PHP') does the job of loading the JSONP with the respective currency types of 'USD' and 'PHP'
  • xRatePHP = rate assigns the right hand side which is rate to xRatePHP. But this line gave us a problem! our console pal told us that rate is undefined!

The truth: mr.console did not lie, rate is actually undefined, however mr.console without any further commands given by you a few moments later if asked again would reply that rate is actually defined. Is this magic?

What is actually happening is that between the time you go from this line

getRate('USD', 'PHP');

to

xRatePHP = rate;

the JSONP response from mr.yahoo hasn't yet come back, which is why when xRatePHP = rate is issued rate seems to be undefined.

Hard Code Solution
Let us hard code a duration for our code to wait before using rate so that we know that mr.yahoo responded, setTimeout will helps us here:

getRate('USD', 'PHP');
setTimeout(function(){alert(rate)}, 2000);

and everything works now! check the demo at: http://jsbin.com/udikas/1/edit

Soft Code
did you ever consider the case where mr.yahoo takes more than 2000 ms to respond? or maybe even lesser than that? (yahoo is pretty fast!) let us instead take a different approach, this will let us use rate the exact moment we calculate it with parseExchangeRate

for this we will have to add a callback from parseExchangeRate:

function parseExchangeRate(data) {

    var name = data.query.results.row.name;
    rate = parseFloat(data.query.results.row.rate, 10);

    alert("Exchange rate " + name + " is " + rate);

}

to

function parseExchangeRate(data) {

    var name = data.query.results.row.name;
    rate = parseFloat(data.query.results.row.rate, 10);

    alert("Exchange rate " + name + " is " + rate);
    gotTheRate(rate)

}

and then change

$(function() {

    getRate('USD', 'PHP');
    alert(rate)

});

to

function gotTheRate(rate){
    alert(rate);
  }

$(function() {

    getRate('USD', 'PHP');
      
});

a demo of this can be found at http://jsbin.com/udikas/2/edit

Multiple Callbacks (in response to question update)

Remember hard coding setTimeouts isn't fun, so let us remove that, manageTimer, q, and other such elements from your code, instead we can have:

function getRate(from, to) {

    var script = document.createElement('script');

    script.setAttribute('src', "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"+from+to+"%253DX%26f%3Dl1n'%20and%20columns%3D'rate%2Cname'&format=json&callback=parseExchangeRate");
    document.body.appendChild(script);

}

function parseExchangeRate(data) {

    var name = data.query.results.row.name;
  
    rateDict[name.match(/USD to ([\w]*)/)[1]] = parseFloat(data.query.results.row.rate, 10);
    total_responses++;
  if (total_responses === rateArr.length){
    for (var k in rateDict){
        alert("USD to " + k + " is " + rateDict[k]);
    }
  }
}

var rate = 1.00;
var timer;
var q;
var rateArr = new Array('PHP','GBP')
var total_responses = 0;
var rateDict = {};

$(function() {

    function getTheRates() {


        for (var x=0; x < rateArr.length; x++) {

            getRate('USD', rateArr[x]);

        }
    }

    getTheRates();
  

}); 

http://jsbin.com/udikas/4/edit

-Relfor


Solution 2:

You should re order your code flow:

function getRate(from, to) {
    var script = document.createElement('script');
    script.setAttribute('src', "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"+from+to+"%253DX%26f%3Dl1n'%20and%20columns%3D'rate%2Cname'&format=json&callback=parseExchangeRate");
    document.body.appendChild(script);
}
function parseExchangeRate(data) {
    var name = data.query.results.row.name;
    var rate = parseFloat(data.query.results.row.rate, 10);
    alert("Exchange rate " + name + " is " + rate);
    xRatePHP = rate;
    /* Do stuff with rate */
}
$(function() {
    getRate('USD', 'PHP');
    // rate is not yet available here, so don't do anything with it
});

Solution 3:

try to put:

var rate = 0;

on top of your code. This will fix the error. Then you have to consider that if you get 0 maybe you are reading the variable at the wrong time, before it gets populated.


Post a Comment for "How Can I Get This JSONP Call To Return A Value?"