11

这是我在13年初写的文章,当时懵懵懂懂写下了自己对JSONP的理解。

文章原文

博客 欢迎订阅


提到JSONP,我当时在网上找了无数帖子也没有看懂它。那些文章大同小异,都是讲到JSONP原理以后就戛然而止,把我们这些初学者搞得云里雾里。所以,写下这篇文章,希望对大家有帮助!

为什么要有JSONP

回答这个问题之前,大家先想想什么是AJAX,JSONP就是一种能够解决AJAX办不到的事情而存在的一种取数据的技术。什么事情是AJAX办不到的呢?就是跨域!

跨域:顾名思义,就是当前网页的地址和我们要取的数据地址不在一个域下。这是因为浏览器都有一个“同源策略”— 两个页面的域名必须在同域的情况下,才能允许通信。

怎么才算一个域呢?

相同域名,相同端口,相同协议(因为不是这里的重点,大家可以请教Google)

“同源策略”的意义:“同源策略”有效地阻止了一些危险行为,比如你进入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 PaddingJSON大家这都知道,是一种数据通信格式,而”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的实例:

62504685.jpg

先查看demo

分析一下:

1.分析数据地址回顾上面的例子,我们首先要知道数据的来源地址,就是上面的www.bbb.com/abc.js里的数据。在Chrome中查看Network。然后随便在搜索框里输入点什么,比如s,观察Network里是不是多了东西,点开它,就是我们输入“s”后传回的数据了:

82372497.jpg

这个地址是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函数:

28602969.jpg

这样,我们的数据就包在了succ函数里做一个参数,再次证明了JSON with Padding 的原理。

2.做<script>标签,其src指向数据地址:这是要动态生成的,不能把地址写死,要不然取到的都是一样的数据了。所以我们要动态生成<script>,动态指定src属性:

var oScript = document.createElement('script');
oScript.src = 'http://suggestion.baidu.com/su?wd='+oTxt.value+'&amp;p=3&amp;cb=succ&amp;from=superpage';
document.body.appendChild(oScript);

3.不要以为这样问题就解决了,F12一下,就看到生成了好多<script>!这是因为我们每输入一个字符就动态生成一个<script>,造成了代码冗余!解决一下:

if(oScript){
document.body.removeChild(oScript);
}

好,这样,我们的搜索框效果就做好了,因为主要讲JSONP部分的工作原理,就不做成百度下拉框那样了,大家可以自己去布局。当然,真正的百度搜索框还要在此基础上涉及事件的冒泡取消等等,就不是这里的重点了,不做阐述。

JSONP总结

  1. JSONP是为了传数据而存在的技术。网页之间的通信原本有AJAX就够了,而AJAX因为浏览器“同源策略”面对跨域情况就束手无策了。JSONP就这样被发明了,利用<script>src属性不受“同源策略”的控制,“作弊”般地巧妙地逃过了浏览器的这一限制。

  2. JSONP方法本质是创建<script>标签,其src指向我们的数据地址。地址后面附带一个回调函数(名字一般是callback或者是别的什么,就看后台给我们的是什么了,函数名是我们起的)。然后,声明这个回调函数。这样,只要一引入上面的<script>标签,就相当于执行了那个回调函数。

  3. 虽然jQuery把JSONP内置在了AJAX里,但是我们一定要清楚,AJAX和JSONP是完全不一样的,一定不要混淆!以后我会更新一篇介绍AJAX的文章的。

  4. 这里是前端和后台的交汇之处,想要真正融会贯通,还要学学后台的知识。我也是在学了PHP之后才把JSONP搞懂的。


一波不是一波
1.7k 声望91 粉丝