同源策略
@H_301_0@ 为什么会出这样的错误呢?这是因为所有支持Javascript的浏览器都会使用同源策略这个安全策略。看看百度的解释:@H_301_0@ 同源策略,它是由Netscape提出的一个著名的安全策略。现在所有支持JavaScript 的浏览器都会使用这个策略。所谓同源是指,域名,协议,端口相同。当一个浏览器的两个tab页中分别打开来 百度和谷歌的页面当一个百度浏览器执行一个脚本的时候会检查这个脚本是属于哪个页面的,即检查是否同源,只有和百度同源的脚本才会被执行。@H_301_0@ 这就是引起为何取不到数据的原因了,那如何才能解决跨域的问题呢?没错,我们现在可以进入正题,来了解下什么是JSONP了。
JSON和JSONP
@H_301_0@ JSONP和JSON好像啊,他们之间有什么联系吗? @H_301_0@ JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。对于JSON大家应该是很了解了吧,不是很清楚的朋友可以去json.org上了解下,简单易懂。 @H_301_0@ JSONP是JSON with Padding的略称。它是一个非官方的协议,它允许在服务器端集成Script tags返回至客户端,通过javascript callback的形式实现跨域访问(这仅仅是JSONP简单的实现形式)。--来源百度 @H_301_0@ JSONP就像是JSON+Padding一样(Padding这里我们理解为填充), 我们先看下面的小例子然后再详细介绍。跨域的简单原理
@H_301_0@ 光看定义还不是很明白,那首先我们先来手动做个简单易懂的小测试。新建一个asp.net的web程序,添加sample.html网页和一个test.js文件,代码如下: @H_301_0@sample.html的代码:1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 2 <html xmlns="http://www.w3.org/1999/xhtml" > 3 <head> 4 <title>test</title> 5 <script type="text/javascript" src="test.js"></script> 6 </head> 7 <body> 8 </body> 9 </html>
1 alert("success");
1 <script type="text/javascript" src="http://localhost:20002/test.js"></script>
JSONP的实现模式--CallBack
@H_301_0@ 刚才的小例子讲解了跨域的原理,我们回上去再看看JSONP的定义说明中讲到了javascript callback的形式。那我们就来修改下代码,如何实现JSONP的javascript callback的形式。 @H_301_0@程序A中sample的部分代码:1 <script type="text/javascript"> 2 //回调函数 3 function callback(data) { 4 alert(data.message); 5 } 6 </script> 7 <script type="text/javascript" src="http://localhost:20002/test.js"></script>
1 <script type="text/javascript"> 2 function callback(data) { 3 alert(data.message); 4 } 5 //添加<script>标签的方法 6 function addScriptTag(src){ 7 var script = document.createElement('script'); 8 script.setAttribute("type","text/javascript"); 9 script.src = src; 10 document.body.appendChild(script); 11 } 12 13 window.onload = function(){ 14 addScriptTag("http://localhost:20002/test.js"); 15 } 16 </script>
1 <script type="text/javascript"> 2 //添加<script>标签的方法 3 function addScriptTag(src){ 4 var script = document.createElement('script'); 5 script.setAttribute("type","text/javascript"); 6 script.src = src; 7 document.body.appendChild(script); 8 } 9 10 window.onload = function(){ 11 //搜索apple,将自定义的回调函数名result传入callback参数中 12 addScriptTag("http://ajax.googleapis.com/ajax/services/search/web?v=1.0&q=apple&callback=result"); 13 14 } 15 //自定义的回调函数result 16 function result(data) { 17 //我们就简单的获取apple搜索结果的第一条记录中url数据 18 alert(data.responseData.results[0].unescapedUrl); 19 } 20 </script>
像这样的JSONP服务还有很多(以下信息来自使用 JSONP 实现跨域通信,第 1 部分: 结合 JSONP 和 jQuery 快速构建强大的 mashup):
@H_301_0@Digg API:来自 Digg 的头条新闻: @H_301_0@ http://services.digg.com/stories/top?appkey=http%3A%2F%2Fmashup.com&type=javascript&callback=? @H_301_0@Geonames API:邮编的位置信息: @H_301_0@ http://www.geonames.org/postalCodeLookupJSON?postalcode=10504&country=US&callback=? @H_301_0@Flickr JSONP API:载入最新猫的图片: @H_301_0@ http://api.flickr.com/services/Feeds/photos_public.gne?tags=cat&tagmode=any&format=json&jsoncallback=? @H_301_0@Yahoo Local Search API:在邮编为 10504 的地区搜索比萨: @H_301_0@ http://local.yahooapis.com/LocalSearchService/V3/localSearch?appid=YahooDemo&query=pizza&zip=10504&results=2&output=json&callback=?@H_301_0@ 接下来我们自己来创建一个简单的远程服务,实现和上面一样的JSONP服务。还是利用Web程序A和程序B来做演示,这次我们在程序B上创建一个MyService.ashx文件。 @H_301_0@程序B的MyService.ashx代码:
1 public class MyService : IHttpHandler 2 { 3 public void ProcessRequest(HttpContext context) 4 { 5 //获取回调函数名 6 string callback = context.Request.QueryString["callback"]; 7 //json数据 8 string json = "{\"name\":\"chopper\",\"sex\":\"man\"}"; 9 10 context.Response.ContentType = "application/json"; 11 //输出:回调函数名(json数据) 12 context.Response.Write(callback + "(" + json + ")"); 13 } 14 15 public bool IsReusable 16 { 17 get 18 { 19 return false; 20 } 21 } 22 }
1 <script type="text/javascript"> 2 function addScriptTag(src){ 3 var script = document.createElement('script'); 4 script.setAttribute("type","text/javascript"); 5 script.src = src; 6 document.body.appendChild(script); 7 } 8 9 window.onload = function(){ 10 //调用远程服务 11 addScriptTag("http://localhost:20002/MyService.ashx?callback=person"); 12 13 } 14 //回调函数person 15 function person(data) { 16 alert(data.name + " is a " + data.sex); 17 } 18 </script>
jQuery对JSONP的实现
@H_301_0@ jQuery框架也当然支持JSONP,可以使用$.getJSON(url,[data],[callback])方法(详细可以参考http://api.jquery.com/jQuery.getJSON/)。那我们就来修改下程序A的代码,改用jQuery的getJSON方法来实现(下面的例子没用用到向服务传参,所以只写了getJSON(url,[callback])):<script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script> <script type="text/javascript"> $.getJSON("http://localhost:20002/MyService.ashx?callback=?",function(data){ alert(data.name + " is a a" + data.sex); }); </script>
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script> <script type="text/javascript"> $.ajax({ url:"http://localhost:20002/MyService.ashx?callback=?",dataType:"jsonp",jsonpCallback:"person",success:function(data){ alert(data.name + " is a a" + data.sex); } }); </script>