以下函数的目的是访问雅虎服务器上的脚本并查找实时货币兑换率,稍后将用于处理客户的购买。
我能够访问 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 */
});
当我尝试在 Jquery 函数中访问它时,Firebug 通知我 rate
未定义。
我尝试的另一件事是将 http 请求的最后一个参数设置为 callback=rate=parseExchangeRate
,这(不足为奇)也不起作用。
更新
@Relfor 解决了最初的问题,即 rate
没有在全局范围内正确声明为全局变量。我解决了这个问题,然后发现了另一个问题,有些人还在下面发现了这个问题,那就是在调用 getRate()
之后(可能需要大约 2000 毫秒来更新变量 rate
),脚本立即继续运行,无需等待 rate
更新并使用 rate,无论它是否准备就绪。
我尝试尝试使用 window.setInterval
来创建延迟来解决这个问题,当我注意到他们仍在线程中事件时,即使我已经接受了@Relfor's答案,所以我宁愿把它带回这里,这样当我们开始工作时,其他人可以从解决方案中受益。
有一个最终(我希望 - 最终!) 问题,那就是为了简化发布的原始问题,我没有透露我实际上试图从雅虎! (可能还有一些计划)因此,我在循环中调用 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 +')');
没有它,计时器似乎没有启动!我不知道为什么,但我不能留下那行。
最佳答案
尚 undefined variable rate
$(function() {
getRate('USD', 'PHP');
xRatePHP = rate;
/* Do stuff with rate */
});
在研究了你的代码之后,似乎 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);
}
如果您希望可以从函数命名空间访问速率而不从内部声明它们,那么必须在全局命名空间中指定速率,它在任何函数或循环之外。
编辑: namespace 问题已解决,我给出的答案已被接受,但我想在此处添加有关您正在处理的代码的详细信息。它取自这里的要点: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')
负责加载 JSONP 以及相应的货币类型“USD”和“PHP”xRatePHP = rate
将右边的rate
分配给xRatePHP
。 但是这条线给我们带来了问题!我们的控制台 friend 告诉我们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 毫秒才能响应的情况?或者甚至比这更少? (yahoo 非常快!)让我们采用不同的方法,这将让我们使用 rate
exact moment 我们用 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
关于javascript - 我怎样才能让这个 JSONP 调用返回一个值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17465011/