以下功能的目的是访问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()之后(可能需要大约2000ms来更新变量rate),脚本立即继续运行而无需等待进行更新并使用费率,而不管其是否准备就绪。

我尝试过尝试使用rate来创建延迟来解决此问题,但是当我注意到即使我已经接受@Relfor的回答时,它们仍然在线程中处于活动状态,所以我宁愿带上它回到这里,以便我们进行这项工作时,其他人可以从解决方案中受益。

有一个最终(我希望-最终!)问题,那就是为了简化原始发布问题,我忽略了透露自己实际上是在尝试从Yahoo!获得两个汇率。 (可能还有更多计划),因此,我在循环中调用window.setInterval,如下所示:

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 */

});


有人建议我将getRate()移到函数/* Do stuff with the rates */内,但不确定我的建议是否仍然有效,因为我有一个循环调用parseExchangeRate()的启示?

UPDATE 3(替代更新2)

我在这里创建了一个JSbin:http://jsbin.com/udikas/3/edit,上面的代码除了这两个问题外似乎都在起作用:

1)超时机制似乎不起作用。

2)在第33行的getRate()行中,计时器似乎无法启动!我不知道为什么,但是我不能留下那条线。

最佳答案

变量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);

}


如果您希望可以从函数名称空间访问速率而不在内部声明速率,则必须在全局名称空间中指定速率,该名称空间位于任何函数或循环之外。

编辑:名称空间问题已解决,我给出的答案已被接受,但是我想在此添加有关您正在处理的代码的详细信息。它是从此处摘录的: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')可以使用相应的货币类型“ USD”和“ PHP”加载JSONP
xRatePHP = rate将右侧的rate分配给xRatePHP。但是这条线给我们带来了问题!我们的控制台好友告诉我们rate未定义!


事实是:mr.console没说谎,rate实际上是未定义的,但是几分钟后如果您再没有给出任何其他命令的情况下,mr.console先生会再次被询问会回答rate实际上是定义的。这是魔法吗?

实际发生的情况是您从这条线走的时间之间

getRate('USD', 'PHP');




xRatePHP = rate;


来自mr.yahoo的JSONP响应尚未返回,这就是为什么发布xRatePHP = raterate似乎未定义的原因。

硬编码解决方案
让我们对使用rate之前的代码进行等待时间的硬编码,以便我们知道mr.yahoo做出了响应,setTimeout将在这里为我们提供帮助:

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


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

软代码
您是否曾经考虑过Yahoo先生花费超过2000毫秒进行回复的情况?甚至比这还小? (yahoo相当快!)让我们采取一种不同的方法,这将使我们使用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和其他类似元素,而可以拥有:

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

-埃尔福

关于javascript - 如何获取此JSONP调用以返回值?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/17465011/

10-11 13:35