什么是jsonp
- 一个众所周知的问题,Ajax直接请求普通文件存在跨域无权限访问的问题,甭管你是静态页面、动态网页、web服务、WCF,只要是跨域请求,一律不准;
不过我们又发现,web页面上调用js文件时不受是否跨域的影响(不仅如此,凡是拥有”src”这个属性的标签都拥有跨域能力,如
<script>、<img>、<iframe>)于是可以判断,当前阶段如果想通过纯web端(ActiveX控件、服务端代理、属于未来的HTML5之Websocket等方式不算)跨域访问数据就只有一种可能,那就是在远程服务器上设法把数据装进js格式的文件里,供客户端调用和进一步处理;
恰巧我们已经知道有一种叫做JSON的纯字符数据格式可以简洁的描述复杂数据,更妙的是JSON还被js原生支持,所以在客户端几乎可以随心所欲的处理这种格式的数据;
这样子解决方案就呼之欲出了,web客户端通过与调用脚本一模一样的方式,来调用跨域服务器上动态生成的js格式文件(一般以JSON为后缀),显而易见,服务器之所以要动态生成JSON文件,目的就在于把客户端需要的数据装入进去。
客户端在对JSON文件调用成功之后,也就获得了自己所需的数据,剩下的就是按照自己需求进行处理和展现了,这种获取远程数据的方式看起来非常像AJAX,但其实并不一样。
为了便于客户端使用数据,逐渐形成了一种非正式传输协议,人们把它称作JSONP,该协议的一个要点就是允许用户传递一个callback参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据,这样客户端就可以随意定制自己的函数来自动处理返回数据了。
原生jsonp解决跨域问题
使用原生jsonp解决跨域问题需要两个步骤
- 定义一个函数,负责解析jsonp接口传过来的数据,就是下面例子传过来的天气数据
- 调用接口,调用方式使用创建一个script标签,添加到页面上
天气查询实例
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>获取第三方天气数据</title>
<style type="text/css">
#div1{
position:relative;
left: 50%;
background: lightGreen;
width: 300px;
height: 500px;
overflow-y: scroll;
overflow-x: hidden;
margin-left: -150px;
padding-bottom: 20px;
}
#div1 select{
margin-left : 80px;
margin-top : 10px;
height: 30px;
}
#div1 input{
height: 30px;
}
#div1 div{
width: 300px;
background: lightBlue;
border-bottom: red solid 1px;
}
#div1 div ul li{
list-style-type: none;
padding-left: 10px;
}
</style>
<script type="text/javascript">
function abc(data){
var d = data.weather;
var info = document.getElementById('info');
info.innerHTML = '';
for(var i=0;i<d.length;i++){
var date = d[i].date;
var day = d[i].info.day;
var night = d[i].info.night;
var tag = '';
tag += '<span>日期:'+date+'</sapn><ul>';
tag += '<li>白天天气:'+day[1]+'</li>'
tag += '<li>白天温度:'+day[2]+'</li>'
tag += '<li>白天风向:'+day[3]+'</li>'
tag += '<li>白天风速:'+day[4]+'</li>'
tag += '</ul>';
tag += '<ul>';
tag += '<li>夜间天气:'+night[1]+'</li>'
tag += '<li>夜间温度:'+night[2]+'</li>'
tag += '<li>夜间风向:'+night[3]+'</li>'
tag += '<li>夜间风速:'+night[4]+'</li>'
tag += '</ul>';
var div = document.createElement('div');
div.innerHTML = tag;
info.appendChild(div);
}
}
window.onload = function(){
var city = document.getElementById('city');
city.onchange = function(){
document.getElementById('info').innerHTML = '';
}
var btn = document.getElementById('btn');
btn.onclick = function(){
var cityCode = city.value;
var url = 'http://cdn.weather.hao.360.cn/api_weather_info.php?app=hao360&_jsonp=abc&code='+city.value;
var script = document.createElement('script');
script.src = url;
document.body.appendChild(script);
}
}
</script>
</head>
<body>
<div id="div1">
<select id="city">
<option value="101010100">北京</option>
<option value="101020100">上海</option>
<option value="101280101">广州</option>
<option value="101280601">深圳</option>
</select>
<input type="button" value="查看天气" id="btn">
<div id="info"></div>
</div>
</body>
</html>
jquery对jsonp的实现
jquery在处理jsonp类型的ajax时,自动生成回调函数并把数据取出来供success属性方法来调用
<!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>
ajax与jsonp的异同之处
1.ajax和jsonp这两种技术在调用方式上“看起来”很像,目的也一样,都是请求一个url,然后把服务器返回的数据进行处理,因此jquery和ext等框架都把jsonp作为ajax的一种形式进行了封装;
2.但ajax和jsonp其实本质上是不同的东西。ajax的核心是通过XmlHttpRequest获取非本页内容,而jsonp的核心则是动态添加