jQuery中利用JSONP解决AJAX跨域问题
蓝飞 | 时间:2012-08-10, Fri | 32,711 views前端开发 写在前面
跨域的解决方案有多种,其中最常见的是使用同一服务器下的代理来获取远端数据,再通过ajax进行读取,而在这期间经过了两次请求过程,使得获取数据的效率大大降低,这篇文章蓝飞就为大家介绍一下解决跨域问题的一种比较通用的方案——JSONP。
什么是跨域?简单的来说,出于安全方面的考虑,页面中的无法访问其他服务器上的数据,即“同源策略”。而跨域就是通过某些手段来绕过同源策略限制,实现不同服务器之间通信的效果。
具体策略限制情况可看下表:
URL 说明 允许通信
同一域名下
允许
同一域名下不同文件夹
允许
:8000/a.js
同一域名,不同端口
不允许
https://www.a.com/b.js
同一域名,不同协议
不允许
域名和域名对应ip
不允许
主域相同,子域不同
不允许
同一域名,不同二级域名(同上)
不允许
不同域名
不允许
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,而JSONP(JSON with Padding)则是JSON 的一种“使用模式”,通过这种模式可以实现数据的跨域获取。
JSONP跨域的原理在同源策略下,在某个服务器下的页面是无法获取到该服务器以外的数据的,但img、iframe、script等标签是个例外,这些标签可以通过src属性请求到其他服务器上的数据。利用script标签的开放策略,我们可以实现跨域请求数据,当然,也需要服务端的配合。当我们正常地请求一个JSON数据的时候,服务端返回的是一串JSON类型的数据,而我们使用JSONP模式来请求数据的时候,服务端返回的是一段可执行的JavaScript代码。
举个例子,假如需要从服务器(?id=123)获取的数据如下:
{"id": 123, "name" : "张三", "age": 17}那么,使用JSONP方式请求(?id=123?callback=foo)的数据将会是如下:
foo({"id": 123, "name" : "张三", "age": 17});当然,如果服务端考虑得更加充分,返回的数据可能如下:
try{foo({"id": 123, "name" : "张三", "age": 17});}catch(e){}以PHP为例,服务端的代码应该如下:
$json = json_encode(array("id" => 123, "name" => "张三", "age" => 17)); if(isset($_GET['callback'])){ $json = 'try{' . $_GET['callback'] . '(' . $json . ')}catch(e){}'; } echo $json;这时候我们只要定义一个foo()函数,并动态地创建一个script标签,使其的src属性为?id=123?callback=foo:
<script type="text/javascript" src="http://www.a.com/user?id=123?callback=foo"></script>便可以使用foo函数来调用返回的数据了。
在jQuery中如何通过JSONP来跨域获取数据第一种方法是在ajax函数中设置dataType为'jsonp':
$.ajax({ dataType: 'jsonp', url: 'http://www.a.com/user?id=123', success: function(data){ //处理data数据 } });第二种方法是利用getJSON来实现,只要在地址中加上callback=?参数即可:
$.getJSON('http://www.a.com/user?id=123&callback=?', function(data){ //处理data数据 });也可以简单地使用getScript方法:
//此时也可以在函数外定义foo方法 function foo(data){ //处理data数据 } $.getScript('http://www.a.com/user?id=123&callback=foo'); JSONP的应用JSONP在开放API中可以起到非常重要的作用,开放API一般是运用于开发者的应用上,而这些应用往往是在开发者的服务器上而并非在新浪微博的服务器上,因此跨域请求数据成为前端开发者们所需要解决的一大问题,广大开放平台应该实现对JSONP的支持,这一点新浪微博开放平台便做的非常好(虽然某些API里没有说明,但实际上是可以使用JSONP方式调用的)。
如需转载请注明出处:蓝飞技术部落格
标签:, JSON, AJAX
下一篇
19 条评论 »
hP
ajax做得很好啊!背景的话,如果是仿ios界面,应该是不动的吧。
蓝飞
背景= =?
我这倒是没模仿IOS的哦,自己随便弄的= =。。
hP
啊。。我说左边导航栏的 织纹背景
蓝飞
的确是不动的呀,如果是在支持position:fixed的浏览器下的话。
麦田麦穗
请问你的这个代码高亮显示的插件是什么?怎么配置的?
蓝飞
@麦田麦穗
Google Code Prettify
hah
第二种方法应该加 ?callback=?
蓝飞
是的
simpleDean
请问服务端的代码应该如何编写呢?
蓝飞
判断是否有callback参数,若有,则加上函数调用代码。
详见上文『以PHP为例,服务端的代码应该如下』部分。
hudonghuicom
?ctId=1&ttId=2&curpage=1&pagesize=10比如这样一个数据我怎么调取json,,再如这个内网的 :86/am/touristMap.aspx?scenicId=11685怎么弄
蓝飞
纯前端的话需要该接口支持JSONP,否则就用PHP之类的进行代理。
julie
写的很详细,很有帮助啊
沉冰浮水
和返回
var foo = {"id": 123, "name" : "张三", "age": 17};
对比该怎么理解呢?同步和异步的差别?
然后这主题是自己弄的么?好想扒。。
蓝飞