如何让此 JSONP 调用返回值

How can I get this JSONP call to return a value?

本文关键字:调用 返回值 JSONP      更新时间:2023-09-26

以下函数的目的是访问雅虎服务器上的脚本并查找实时货币兑换率,该汇率稍后将用于处理客户的购买。

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

我在parseExchangeRate()函数结束时尝试了标准return rate;,但不起作用。我也尝试将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 */
});

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

我尝试的另一件事是将 http 请求的最后一个参数设置为 callback=rate=parseExchangeRate 这也不起作用(毫不奇怪(。

更新

@Relfor解决了最初的问题,即rate未在全局范围内正确声明为全局变量。我修复了这个问题,然后发现了一个进一步的问题,有些人也在下面发现了这个问题,那就是在调用getRate()后(更新变量rate可能需要大约 2000 毫秒(,脚本立即继续,无需等待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 +')');没有它,计时器似乎不会启动!我不知道为什么,但我不能把那条线留在里面。

变量

rate尚未定义

$(function() {
    getRate('USD', 'PHP');
    xRatePHP = rate;
    /* Do stuff with rate */
});

在研究了您的代码后,似乎 parseExchange(data) 函数中的 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);
}
如果您希望从函数命名空间访问 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请求完成解析时,将调用ExchangeRate。

那么为什么它不起作用呢?

让我再次显示代码:

$(function() {
    getRate('USD', 'PHP');
    xRatePHP = rate;
    /* Do stuff with rate */
});

我们应该分解一下:

  • getRate('USD', 'PHP') 使用各自的货币类型"USD"和"PHP"加载 JSONP
  • xRatePHP = raterate的右侧分配给xRatePHP但是这条线给我们带来了一个问题! 我们的控制台朋友告诉我们,rate是不确定的!

真相:控制台先生没有撒谎,rate实际上是未定义的,但是控制台先生没有给出任何进一步的命令,几分钟后,如果再次被问到,我会回答rate实际上是定义的。这是魔法吗?

实际发生的事情是,在你从这条线出发的时间之间

getRate('USD', 'PHP');

xRatePHP = rate;

雅虎先生的JSONP回应还没有回来,这就是为什么当xRatePHP = rate发布时rate似乎没有定义。

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

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

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

软代码
你有没有考虑过雅虎先生需要超过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 和其他此类元素,相反,我们可以拥有:

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

-瑞福

您应该重新排序代码流:

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

尝试输入:

var rate = 0;

在您的代码之上。这将修复错误。然后你必须考虑到,如果你得到0,也许你在错误的时间读取变量,在它被填充之前。