JSONP 跨域调取JSON/JS数据
要理解跨域先要了解"同源策略". 所谓同源是指,域名,协议,端口相同。即基于安全考虑,当前域不能访问其他域的东西。
一些常见的是否同源示例可参照下表:
在同源策略下,在某个服务器下的页面是无法获取到该服务器以外的数据的。
JSON(JavaScript Object Notation) 和 JSONP(JSON with Padding)
1. JSON是一种数据交换格式,而JSONP是一种非官方跨域数据交互协议。是一个数据通路的握手的方式。
优点: 纯文本、跨平台、Javascript原生支持、前后端兼容、可读性好易读写。缺点:不知道
JSON数据结构比XML的可读性更好,数据量也少很多。
它使用了如:
大括号 {} 用来描述包含各种类型的元素的集合
方括号 [] 用来描述包含相同类型的元素的组
英文冒号 : 分隔 键值对
英文逗号 , 分隔集合
英文双引号"" 括键值对
它的基本表现形式为键值对,如:{ key : value } key可省略双引号,但最好还是加上,养成良好的习惯。 value 必须用双引号 括起来
它所常用数据类型有:String, Number, Boolean, Date, Null 注:日期类型比较特殊,建议如客户端没有按日期排序功能需求的话把日期时间直接作为字符串传递, 可省去麻烦.
JSON实例:
// 描述多辆车
var cars = [
{"brand":"Benz", "price":200000, "country":"Germany", "expert":"2015-08-15","expensive":true, "members":[{"name":"Henry","age":35},{"name":"Tom","age":32}] },
{"brand":"Qens", "price":100000, "country":"China", "expert":"2015-08-15", "expensive":false, "members":[{"name":"ZhangMi","age":35},{"name":"PengHao","age":30}]}
];
// 读取
var carCountry = cars[1].country;
// 读取Qens是否贵
var qensIsAnExpensive = cars.members[1].expensive;JSONP
JSONP 是 JSON with padding(填充式 JSON 或参数式 JSON)的简写。
JSONP实现跨域请求的原理简单的说,就是动态创建<script>
标签,然后利用<script>
的src 不受同源策略约束来跨域获取数据。
各种各样的文件 在 跨域请求中的限制造就了JSONP的出现,浏览器中带有src属性的 都不受跨域的限制,但<img>
的src(获取图片)、<link>
的href(获取css)、<script>
的src(获取JavaScript)、<iframe>(获取html)这些都不符合同源策略,它们可以跨域获取数据。这里要介绍的JSONP就是利用<script>
的src来实现跨域获取数据的。
如<script>、<img>、<iframe>, 在服务端把数据动态生成JSON模拟成JS文件传给客户端以便处理。感觉像是给数据穿了件马甲! 客户端接到数据后转成自己想要的JSON绑定到页面即可。
前后端给定一个callback参数,前端传递一个callback参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据。
动态创建<script>标签,设置其src,回调函数在src中设置:
var script = document.createElement("script");
script.src = "http://xxx/search?q=javascript&name=henry&callback=Test";
document.getElementsByTagName('head')[0].appendChild(script);
1、我们知道,哪怕跨域js文件中的代码(当然指符合web脚本安全策略的),web页面也是可以无条件执行的。
- Server端: http://www.baidu.com/a.js
- Local端: http://localhost/jsonp.html
a.js:
Test({"name":"henry"});
<script>
//a.js Test({"name":"henry"});
function Test(d){
console.log(d);//{"name":"henry"}
}</script>
<script type="text/javascript" src="http://www.baidu.com/a.js"></script>
注意:引用外部<script>的a.js时, 前后顺序要注意, 引用的a.js 相当于调用了 function Test(d){...}, 所以必须先定义后引用.
服务器就按客户端的需求来动态生成Javascript脚本
jsonp.html:<script>
var Test = function(data){ alert(data); };
// 提供JSONP服务的URL地址, 不管是形式的URL地址结果返回的都是JS
var url = "http://www.baidu.com/json.asp?name=henry&callback=Test";// name=henry 传递的参数 callback=Test 约定的握手的方式
// 动态生成script并插入到document.head中
var script = document.createElement('script');script.setAttribute('src', url);
document.getElementsByTagName('head')[0].appendChild(script);
</script>
json.asp:
... 这里通过URL传递过来的参数(name=henry)来判断处理并以下面的方式返回Local端需要的JS结果
Test({ "name": "henry", "age": 35, "married": true});
如果你用的是第三方JS库, 可用如下方式实现JSONP读取JS数据
$.ajax({
type: "get",
async: false,
url: "http://www.baidu.com/json.asp?name=henry",
dataType: "jsonp",
jsonp: "callback", //一般默认用:callback
jsonpCallback:"Test", //约定的握手方式, 第三方JS库一般会自动执行并生成这个回调函数, 返回执行后的您所需要的数据
success: function(jsonData){
alert('姓名: ' + jsonData.name + ', 年龄: ' + jsonData.age);
},
error: function(){
alert('error');
}
});
JSON的缺点:
- 安全性无法保障,如果不是自己可维护的Web服务端时, 必须事先确定JSONP调用的无恶意脚本代码。
- 暂时没有确定调用JSONP数据出错的事件,现在大多用指定超时时间(毫秒)以确定是否调取数据失败。