如何获取此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.yahoo需要超过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
并不好玩,所以让我们从你的代码中删除, manageTimer
, q
和其他这样的元素,而不是我们可以:
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,你可能在错误的时间读取变量,然后才能填充它。