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

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

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

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

 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 (这并不奇怪)它也不起作用。

UPDATE

@Relfor解决了原始问题,即在全局范围内未将该rate正确地声明为全局变量。 我解决了这个问题,然后发现了另一个问题,有些人也在下面发现了这个问题,即在调用getRate getRate()之后(可能需要大约2000ms才能更新变量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  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 */ }); 

有人建议我在函数parseExchangeRate()移动/* Do stuff with the rates */但是不确定这个建议是否仍然存在,因为我在循环中调用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)函数中定义了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而不从内部声明它们,则必须在全局名称空间中指定速率,该名称空间位于任何函数或循环之外。

编辑 :名称空间问题已经解决,我已经接受了答案,但是我想在此处添加有关您正在处理的代码的详细信息。 它来自这里的要点: 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 

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

那么为什么它不起作用?

让我再次显示代码:

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

我们应该打破这个:

  • getRate('USD', 'PHP')负责使用相应的货币类型’USD’和’PHP’加载JSONP
  • xRatePHP = rate指定右侧,这是xRatePHP rate但是这条线给了我们一个问题! 我们的控制台朋友告诉我们, 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和其他这样的元素,而不是我们可以:

 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

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

 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,你可能在错误的时间读取变量,然后才能填充它。