如何获取此JSONP调用以返回值?

时间:2013-07-04 08:07:01

标签: javascript jquery callback return jsonp

以下功能的目的是访问Yahoo服务器上的脚本并查找实时货币转换率,以后将用于处理客户的购买。

我能够访问JavaScript警报中的费率,但我似乎无法将它们返回到最初称为getRate()函数的Jquery方法。

我在return rate;函数的末尾尝试了一个标准parseExchangeRate(),但这不起作用。我还尝试将rate设置为parseExchangeRate()中的全局变量,但这也不起作用。

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;
    rate = parseFloat(data.query.results.row.rate, 10);

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

}

$(function() {

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

    /* Do stuff with rate */

});

当我尝试在Jquery函数中访问它时,Firebug通知我rate未定义。

我尝试的另一件事是将http请求的最后一个参数设置为callback=rate=parseExchangeRate,这也就是说(不足为奇)。

更新

@Relfor解决了原始问题,即rate未在全局范围内正确声明为全局变量。我修复了这个问题,然后发现了另一个问题,有些人也在下面发现了这个问题,即在调用getRate()之后(可能需要大约2000毫秒来更新变量rate),脚本立即继续运行等待rate更新并使用率,无论它是否准备就绪。

我尝试使用window.setInterval创建延迟来解决这个问题,当我注意到他们仍然在线程中活动时,即使我已经接受了@ Relfor的答案,所以我'我宁愿把它带回这里,这样当我们开始工作时,其他人也可以从解决方案中受益。

有一个最终的(我希望 - 最终!)问题,那就是为了简化发布的原始问题,我省略了透露我实际上是想从两个雅虎(可能还有一些计划)因此,我在循环中调用getRate()如下:

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;
    rate = parseFloat(data.query.results.row.rate, 10);

}

var rate = 1.00;
var timer;
var q;
var xRatePHP, xRateGBP;
$(function() {

    function getTheRates() {

        var rateArr = new Array('PHP','GBP');

        for (var x=0; x < rateArr.length; x++) {
            getRate('USD', rateArr[x]);

            q = 0;
            timer = window.setInterval(function(){manageTimer(rateArr[x])},100);

        }
    }

    function manageTimer(c) {

        if (rate != 1) {

            window.clearInterval(timer);

            /* Note that 'c' is undefined according to 'alert' below,
             * so this next line is not working correctly.
             */
            eval("xRate"+c+" = rate;"); 


            alert(c + " = " + rate); // displays 'undefined 43.543'

            rate = 1.00;

        }

        q++;

        if (q > 30 ) {

            window.clearInterval(timer);

            // added below because above isn't working (but neither does this!)
            timer = '';
            alert(c+' timeout'); // 'c' is undefined according to alert ???
            q = 0;

        }

    }

    getTheRates();

    /* Do stuff with the rates */

});

有人建议我将/* Do stuff with the rates */移到函数parseExchangeRate()内但不确定这个建议是否会因为我在循环中调用getRate()的启示而持续​​存在?

更新3(替换更新2)

我在这里创建了一个JSbin:http://jsbin.com/udikas/3/edit以上,除了这两个问题之外,它似乎正在起作用:

1)超时机制似乎无法正常工作。

2)在第33行这一行alert('start timer (' + x +')');没有它,计时器似乎没有启动!我不明白为什么,但我不能留下那条线。

3 个答案:

答案 0 :(得分:3)

尚未定义变量rate

$(function() {

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

    /* Do stuff with rate */

});

在研究代码后,似乎费率在parseExchange(data)函数中定义为

function parseExchangeRate(data) {

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

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

}

如果您希望从函数名称空间访问rate而不从内部声明它们,则必须在全局名称空间中指定rate,这在任何函数或循环之外。

编辑:命名空间问题已经解决,我已经接受了我给出的答案,但是我想在此处添加有关您正在处理的代码的详细信息。它来自这里的要点:https://gist.github.com/henrik/265014

我们正在处理JSONP

parseExchangeRate存在的原因及其上下文乍一看似乎很神秘,尽管它的存在是您的JSONP请求与响应返回的数据之间的主要联系。

如果您仔细查看请求:

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

(我将链接分成许多行以便于阅读)
仔细查看网址的最后一部分:callback=parseExchangeRate
这是连接,当JSONP请求完成时,将调用parseExchangeRate。

那么为什么它不起作用?

让我再次显示代码:

$(function() {

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

    /* Do stuff with rate */

});

我们应该打破这个:

  • getRate('USD', 'PHP')负责使用相应的货币类型加载JSONP&#39; USD&#39;和&#39; PHP&#39;
  • xRatePHP = rate指定ratexRatePHP的右侧。 但是这条线给了我们一个问题!我们的控制台朋友告诉我们rate未定义!

事实: mr.console没有说谎,rate实际上是未定义的,然而 mr.console 没有您提供任何进一步的命令片刻之后如果再次询问会回复rate实际定义的内容。这真是神奇吗?

实际发生的是你从这一行开始的时间

getRate('USD', 'PHP');

xRatePHP = rate;

来自mr.yahoo的JSONP回复还没有回来,这就是为什么xRatePHP = rate被发布时rate似乎未定义的原因。

硬代码解决方案
让我们硬编码我们的代码在使用rate之前等待的持续时间,以便我们知道mr.yahoo回复了,setTimeout将在这里帮助我们:

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

现在一切正常!查看演示:http://jsbin.com/udikas/1/edit

软代码
你有没有考虑过mr.y​​ahoo需要超过2000毫秒才能响应的情况?或者甚至比那还要小? (雅虎很快!)让我们采取不同的方法,这将让我们使用rate 确切时刻我们用parseExchangeRate

计算它

为此,我们必须添加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);

}

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)

}

然后更改

$(function() {

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

});

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

$(function() {

    getRate('USD', 'PHP');

});

可在http://jsbin.com/udikas/2/edit

找到此演示

多个回调(响应问题更新)

请记住,硬编码setTimeouts并不有趣,所以让我们从您的代码中删除manageTimerq和其他此类元素,而不是我们可以:< / p>

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

答案 1 :(得分:1)

您应该重新订购代码流程:

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
});

答案 2 :(得分:0)

尝试放:

var rate = 0;

代码顶部。这将解决错误。 然后你必须考虑如果你得到0,你可能会在错误的时间读取变量,然后再填充它。