提到JSONP,我当时在网上找了无数帖子也没有看懂它。那些文章大同小异,都是讲到JSONP原理以后就戛然而止,把我们这些初学者搞得云里雾里。所以,写下这篇文章,希望对大家有帮助!
为什么要有JSONP
回答这个问题之前,大家先想想什么是AJAX,JSONP就是一种能够解决AJAX办不到的事情而存在的一种取数据的技术。什么事情是AJAX办不到的呢?就是跨域!
跨域:顾名思义,就是当前网页的地址和我们要取的数据地址不在一个域下。这是因为浏览器都有一个“同源策略”— 两个页面的域名必须在同域的情况下,才能允许通信。
“同源策略”的意义:“同源策略”有效地阻止了一些危险行为,比如你进入www.aaa.com
,同时浏览器又开了一个www.bbb.com
,如果这个www.bbb.com
是一个木马网站,在没有“同源策略”的情况下,它就可能嵌入一些代码,来取得你在www.aaa.com
的信息(因为这时两个页面是可以通信的) 。而正是因为有了“同源策略”,刚才可以通信的情况才不会发生。
“同源策略”带来的麻烦:上面的例子是我们在不知情的情况下,保护我们的网络安全的,但如果我们就是要让www.aaa.com
取得www.bbb.com
上的数据,行不行呢?答:不行!还是因为”同源策略”!我们想从自己信任的网页上取得数据都不行,这可怎么办呢?
JSONP出现
在需要跨域通信的岁月里,一些卓越的前端工程师们想到了这个”作弊”的办法来逃避”同源策略”。”同源策略”虽然很厉害,阻止了一个页面到另一个页面的通信,可是src
指向的路径它放过了,提到src
,大家是不是想起了<script>
?对,JSONP就是利用”同源策略”的这一”漏洞”来进行”作弊”的。(其实有src
属性的不止有<script>
,还有<img>
和<iframe>
,而<iframe>
也是能够运用JSONP
的)。
下面看看JSONP
的原理:
JSONP
:JSON with Padding
,JSON
大家这都知道,是一种数据通信格式,而”Padding”是什么意思,别急,往下看就知道了。
我们先举一个简单的例子:
www.aaa.com
中:
<script type="text/javascript" src="http://www.bbb.com/abc.js"></script>
<script type="text/javascript">
function abc(json){
alert(json['name']);
}
</script>
www.bbb.com/abc.js
中:
abc({'name':'risker','age':24});
页面会弹出risker
,有感觉了么?
JSONP是这样工作的:像前面所说的那样,我们可以取到www.bbb.com/abc.js
,里面是一个abc
函数,这个函数也会被加载到www.aaa.com
。加载完成后,就应该执行abc
了,然后我们在www.aaa.com
定义abc
函数,这个函数里写一些处理数据的语句。这样其实就简单地实现了跨域访问数据了,这也就是JSONP
的原理了。而JSON with Padding
的意思,就是abc(json)
中的json
:abc({'name':'risker','age':24})
。
这个JSON对象被包在abc这个函数中当作参数来被处理,而JSON with Padding
这个词很形象地形容了这个过程。
JSONP的简单实例
在网上能找到的JSON基本只是介绍到这里就完了,但是这让初学者看不到一个实实在在的例子。所以下面才是这篇文章和其他网上介绍JSON文章不一样的地方,我带给大家一个例子!
大家一定对百度的自动搜索框有印象,它就是一个JSONP的实例:
先查看demo
分析一下:
1.分析数据地址回顾上面的例子,我们首先要知道数据的来源地址,就是上面的www.bbb.com/abc.js
里的数据。在Chrome中查看Network。然后随便在搜索框里输入点什么,比如s
,观察Network里是不是多了东西,点开它,就是我们输入“s”后传回的数据了:
这个地址是http://suggestion.baidu.com/su?wd=S&p=3&cb=window.bdsug.sug&from=superpage&t=1365392859833
, 我们分析一下,wd
后面是s
,那就可以断定百度定义wd
是搜索的关键字,cb
是一个回调函数,其他的对我们就不重要了。回调函数是我们取到数据要后执行的函数,相当于我们上面的abc函数。它是可以自己取名的。像http://suggestion.baidu.com/su?wd=S&p=3&cb=succ&from=superpage
表示取到数据后执行succ函数:
这样,我们的数据就包在了succ函数里做一个参数,再次证明了JSON with Padding 的原理。
2.做<script>
标签,其src指向数据地址:这是要动态生成的,不能把地址写死,要不然取到的都是一样的数据了。所以我们要动态生成<script>
,动态指定src
属性:
var oScript = document.createElement('script');
oScript.src = 'http://suggestion.baidu.com/su?wd='+oTxt.value+'&p=3&cb=succ&from=superpage';
document.body.appendChild(oScript);
3.不要以为这样问题就解决了,F12一下,就看到生成了好多<script>
!这是因为我们每输入一个字符就动态生成一个<script>
,造成了代码冗余!解决一下:
if(oScript){
document.body.removeChild(oScript);
}
好,这样,我们的搜索框效果就做好了,因为主要讲JSONP部分的工作原理,就不做成百度下拉框那样了,大家可以自己去布局。当然,真正的百度搜索框还要在此基础上涉及事件的冒泡取消等等,就不是这里的重点了,不做阐述。
JSONP总结
JSONP是为了传数据而存在的技术。网页之间的通信原本有AJAX就够了,而AJAX因为浏览器“同源策略”面对跨域情况就束手无策了。JSONP就这样被发明了,利用
<script>
的src
属性不受“同源策略”的控制,“作弊”般地巧妙地逃过了浏览器的这一限制。JSONP方法本质是创建
<script>
标签,其src
指向我们的数据地址。地址后面附带一个回调函数(名字一般是callback或者是别的什么,就看后台给我们的是什么了,函数名是我们起的)。然后,声明这个回调函数。这样,只要一引入上面的<script>
标签,就相当于执行了那个回调函数。虽然jQuery把JSONP内置在了AJAX里,但是我们一定要清楚,AJAX和JSONP是完全不一样的,一定不要混淆!以后我会更新一篇介绍AJAX的文章的。
这里是前端和后台的交汇之处,想要真正融会贯通,还要学学后台的知识。我也是在学了PHP之后才把JSONP搞懂的。