JSONP详解
1.什么是ajax跨域请求
当通过ajax异步请求其他域名的服务时,存在跨域无权限访问的问题。
此时,可以通过JSONP来实现跨域请求。
2.JSONP原理
ajax异步请求无权限访问。但我们发现,web页面调用js文件时不存在跨域问题(如在我们的页面中引入百度地图API, <script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=e3ZohdqyB0RL98hFOiC29xqh"></script>),总结发现,凡是拥有“src”属性的标签都拥有跨域的能力,如<script>,<img>,<iframe>等。
这种非正式的传输协议,就是JSONP。JSONP的一个要点是允许客户端传一个callback参数给服务器,然后服务器返回数据时会用这个callback参数作为函数名,包裹住JSON数据,返回客户端,客户端执行返回函数。
3.JSONP客户端具体实现
1)直接执行返回函数
本地服务器local.com下有个jsonp.html页面代码如下:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title></title> <script type="text/javascript" src="http://remote.com/remote.js"></script> </head> <body> </body> </html>
远程服务器remote.com下有个remote.js文件代码如下:
alert('我是远程文件');
运行jsonp.html,会弹出“我是远程文件”,显示跨域调用成功。
2)客户端执行回调函数
jsonp.html页面代码如下:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title></title> <script type="text/javascript"> var localHandler = function(data){ alert('我是本地函数,可以被跨域的remote.js文件调用,远程js带来的数据是:' + data.result); }; </script> <script type="text/javascript" src="http://remoteserver.com/remote.js"></script> </head> <body> </body> </html>
remote.js文件代码如下:
localHandler({"result":"我是远程js带来的数据"});
运行jsonp.html,会弹出“我是远程js带来的数据”,显示跨域调用成功。
3)客户端传递回调函数
jsonp.html页面代码如下:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title></title> <script type="text/javascript"> // 得到航班信息查询结果后的回调函数 var flightHandler = function(data){ alert('你查询的航班结果是:票价 ' + data.price + ' 元,' + '余票 ' + data.tickets + ' 张。'); }; // 提供jsonp服务的url地址(不管是什么类型的地址,最终生成的返回值都是一段javascript代码) var url = "http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998&callback=flightHandler"; // 创建script标签,设置其属性 var script = document.createElement('script'); script.setAttribute('src', url); // 把script标签加入head,此时调用开始 document.getElementsByTagName('head')[0].appendChild(script); </script> </head> <body> </body> </html>
flightResult.aspx的页面生成了一段这样的代码提供给jsonp.html
flightHandler({
"code": "CA1998",
"price": 1780,
"tickets": 5
});
运行jsonp.html,成功弹出提示窗口。
4)JSONP封装了3)中的代码,以方便客户端使用。
jsonp.html页面代码如下:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head> <title>Untitled Page</title> <script type="text/javascript" src=jquery.min.js"></script> <script type="text/javascript"> jQuery(document).ready(function(){ $.ajax({ type: "get", async: false, url: "http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998", dataType: "jsonp", jsonp: "callback",//传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(一般默认为:callback) jsonpCallback:"flightHandler",//自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名,也可以写"?",jQuery会自动为你处理数据 success: function(json){ alert('您查询到航班信息:票价: ' + json.price + ' 元,余票: ' + json.tickets + ' 张。'); }, error: function(){ alert('fail'); } }); }); </script> </head> <body> </body> </html>
示例中没有定义flightHandler函数,但代码成功运行了。
这是因为jquery自动把success属性方法作为了回调函数。
4.JSONP总结
由上面的讲解可知,ajax和jsonp两种技术看起来很像,但实质上是完全不同。
5.JSON格式数据优点补充
1)基于纯文本,跨平台传递简单
2)javascript原生支持,后台语言几乎全部支持
3)可读性强
4)容易编写和解析