AJAX经常用来异步请求数据,并且局部更新页面。但是AJAX有一个很大的问题,它只能请求相同域名下的内容。如果是请求不同域名下的内容和数据,不管是什么内容,都不会成功。这就需要JSONP来进行跨域请求数据。
一、 前提
在JS和HTML中,其实跨域是很常见的。img标签、script标签都可以直接跨域来获取其它网站的内容。这就表示,我们通过使用script来跨域请求是完全可行的。而且因为JSON的存在,提供了一种非常适合数据交换的语法格式,而JSON恰好又被原生JS支持。
二、 理解JSONP的三个demo
1. 使用script跨域
本地有一个index.html的文件,内容如下:
<body>
<script src="http://127.0.0.1:8080/test.js"></script>
</body>
本地域名为:127.0.0.1:8081,script标签是在跨域请求
test.js的内容:
alert('我是远程文件')
当在http协议打开index.html文件时,弹出“我是远程文件”,表示跨域成功。
2. 稍微变通一下
远程的test.js改为:
handler({"name":"limingru"})
本地index.html改成:
<body>
<script>
function handler(data){
document.write(data.name)
}
</script>
<script src="http://127.0.0.1:8080/test.js"></script> //这里就相当于在script标签里写了handler({"name":"limingru"}),调用了上面准备好的函数。
</body>
这样,在页面里就写入了limingru了。
3.理解JSONP
写到这里,大致就能理解JSONP的基本逻辑了,JSONP就是通过客户端通过script脚本来跨域调用其它服务器上动态生成的JS格式的文件,而用于交互的数据的格式则是JSON。调用成功以后,客户端就跨域获得了服务器的数据,这样就可以通过JS来展示这些数据了。
到这里还有一个问题。就是拿数据和给数据的双方要共同约定一种格式,JSONP是通过函数参数传递的方式来给数据的,那给数据的一方如何知道拿数据的一方的函数呢?用查询参数来约定,比如callback,它们的值就是共同的函数名称和其它需要的信息。
来看第三个demo:
本地index.html内容为:
<body>
<div></div>
<div></div>
<div></div>
<script>
function handler(data){
var divs = document.querySelectorAll('div')
divs[0].textContent = data.name
divs[1].textContent = data.gender
divs[2].textContent = data.age
}
var url = 'http://127.0.0.1:8080/test.js?callback=handler'
var script = document.createElement('script')
script.setAttribute('src',url)
document.querySelector('body').appendChild(script)
</script>
</body>
index.html文件动态生成script标签,并且加上url,在url还给了一个查询参数callback=handler,它告诉服务器返回一个handler来传递服务器的JSON数据。
服务器会根据查询参数生成相应的test.js文件:
handler({
"name":"limingru",
"gender": "male",
"age": 18
})
并且将相应的数据传过去。这样,在本地页面就能展示跨域获得的数据了。
三、用jQuery通过JSONP跨域获取数据
$.ajax({
type: "get",
async: false,
url: "http://xxx.aspx",
dataType: "jsonp",
jsonp: "callback",//传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(一般默认为:callback)
jsonpCallback:"flightHandler",//自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名,也可以写"?",jQuery会自动为你处理数据
success: function(json){
alert('您查询到航班信息:票价: ' + json.price + ' 元,余票: ' + json.tickets + ' 张。')
},
error: function(){
alert('失败');
}
})
jQuery将JSONP封装到了AJAX里,但实际上它们完全不一样。要记住这一点。