jQuery + JSONP + 雅虎查询语言

Posted

技术标签:

【中文标题】jQuery + JSONP + 雅虎查询语言【英文标题】:jQuery + JSONP + Yahoo Query Language 【发布时间】:2011-03-08 00:50:20 【问题描述】:

我想从外部来源获取实时汇率,所以我发现了这个很棒的网络服务:

Currency Convertor

这项服务的工作方式非常棒,唯一的缺点是它不提供 JSONP 结果,只提供 XML。因此,我们在尝试使用 jQuery $.ajax() 使用此 Web 服务时遇到了跨浏览器问题。

所以我找到了Yahoo Query Language,它以 JSONP 形式返回结果,并且 mangae 使用其他 Web 服务并将结果返回给我。这也有效,这是一个示例 URL:

http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20xml%20where%20url%3D'http%3A%2F%2Fwww.webservicex.net%2FCurrencyConvertor.asmx%2FConversionRate%3FFromCurrency%3DNOK%26ToCurrency%3DEUR'&format=json&diagnostics=true&callback=cbfunc

这个 URL 返回 JSONP 结果并且工作起来很神奇,但是当我在我的代码中使用它时出现了问题:

$.ajax(
  type: "GET",
  url: urlToWebservice,
  contentType: "application/json; charset=utf-8",
  dataType: "jsonp",
  success: function(data) 
    $("#status").html("OK: " + data.text);
  ,
  error: function(xhr, textStatus, errorThrown) 
    $("#status").html("Unavailable: " + textStatus);
  
);

当我尝试运行此代码时,什么也没有发生,我可以在我的 Firebug javascript 调试器中看到此错误消息:

cbfunc is not defined

cbfunc 是围绕 JSON 响应的容器的名称,但为什么它说未定义?

编辑:

这是我的新代码,但我仍然得到cbfunc is not defined

$.ajax(
  url: "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20xml%20where%20url%3D'http%3A%2F%2Fwww.webservicex.net%2FCurrencyConvertor.asmx%2FConversionRate%3FFromCurrency%3DNOK%26ToCurrency%3DEUR'&format=json&callback=cbfunc",
  dataType: 'jsonp',
  jsonp: 'callback',
  jsonpCallback: 'cbfunc'
);

function cbfunc(data) 
  alert("OK");

并且永远不会触发“OK”消息...

【问题讨论】:

Doh.. 愚蠢的我,function cbfunc(data) 在另一个函数中,当我把它作为一个单独的函数放在这个函数之外时,它就可以工作了! 为什么显式指定回调为cbfunc 并且当您可以让jQuery 处理事情并在您的success 回调中正常进行时对该函数的存在有硬依赖,就像您对非-JSONP 调用? 【参考方案1】:

你绝对应该试试 jQuery-JSONP:http://code.google.com/p/jquery-jsonp/

简化一切:)

【讨论】:

【参考方案2】:

它不工作的原因是因为通过在查询字符串中指定callback=cbfunc 会生成一个类型的 URL:

http://query.yahooapis.com/...&callback=cbfunc&callback=jsonp1277417828303

删除了所有不感兴趣的部分,但 URL 包含两个 callback 参数。其中一个由 jQuery 管理,另一个则不是。 YQL 只查看第一个 callback 参数并返回包含该参数的响应。

cbfunc("query":...);

但是,您的脚本中没有名为 cbfunc 的函数,这就是您收到未定义错误的原因。 jQuery 在上面的示例中创建了一个名为 jsonp1277417828303 的隐式函数,而 YQL 的响应应该是:

jsonp1277417828303("query":...);

让 jQuery 对其采取行动,并将响应返回给您的 success 回调,它永远不会这样做。

因此,正如@SLaks 建议的那样,从您的 URL 中删除 &callback=cbfunc,或者将其替换为 &callback=? 以让 jQuery 处理事情。

查看working example。

【讨论】:

【参考方案3】:

如果可用,请在对$.ajax 的调用中使用jsonpCallback 参数,例如:

 jsonpCallback: "cbfunc",

它的描述,来自jQuery API docs:

指定 jsonp 请求的回调函数名称。将使用此值代替 jQuery 自动生成的随机名称。

文档后来继续说:

最好让 jQuery 生成一个唯一的名称,因为这样可以更轻松地管理请求并提供回调和错误处理。当您想要更好地为 GET 请求启用浏览器缓存时,您可能需要指定回调。

但是,建议在使用 YQL 时使用这种“首选”行为。正是这种方法不理想的原因可能会使这个答案过于冗长,所以这里有一个链接(来自 YQL 博客),详细说明了 jQuery 首选方法的问题,使用了jsonpCallback 等等:Avoiding rate limits and getting banned in YQL and Pipes: Caching is your friend

【讨论】:

感谢您的回复,这是一个很棒的博客链接。我阅读了他们写的内容并尝试了他们的 jQuery 示例,但我仍然收到 cbfunc is not defined 消息。我已经编辑了我的帖子以包含我的新代码。【参考方案4】:

您应该让 jQuery 处理回调,方法是将 urlToWebservice 更改为以 callback=? 结尾

【讨论】:

以上是关于jQuery + JSONP + 雅虎查询语言的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法在 CodeIgniter 中使用 jQuery JSONP 而不打开查询字符串?

jsonp跨域请求数据实例之手机号码查询

雅虎金融 API 的查询限制是多少?

PHP 制作雅虎和谷歌搜索查询字符串

YQL查询服务现在被雅虎关闭了

组合查询JSONP