Json&Jsonp

对于JSON和JSONP,应该都不陌生,咳咳,不过最初对JSONP有点误解,以为是JSON的另外一个别名,其实二者风马牛不相及。

谈到Json和jsonp就不可避免要提到跨域这个话题了,以前对跨域的理解都是比较模糊的,还以为域名不同就是跨域了,那太狭隘了。非同源请求,均为跨域。

不过为什么会出现跨域?出于浏览器的同源策略限制,浏览器会拒绝跨域请求。

严格的说,浏览器并不是拒绝所有的跨域请求,实际上拒绝的是跨域的读操作。浏览器的同源限制策略是这样执行的:

通常浏览器允许进行跨域写操作(Cross-origin writes),如链接,重定向;

通常浏览器允许跨域资源嵌入(Cross-origin embedding),如 img、script 标签(主要是有src);

通常浏览器不允许跨域读操作(Cross-origin reads)。*

等等,上面咋又来了个同源策略,本是同根生,相煎何太急啊。

大家互相开开心心的走亲访友多好。哼,谁知道你是我亲戚还是坏人,万一你来我家是想偷小鱼干的呢?还开开心心,本喵不得哭死啊。

同源策略 (Same-Origin Policy) 最早由 Netscape 公司提出, 所谓同源就是要求, 域名, 协议, 端口相同. 非同源的脚本不能访问或者操作其他域的页面对象(如DOM等). 作为著名的安全策略, 虽然它只是一个规范, 并不强制要求, 但现在所有支持 javaScript 的浏览器都会使用这个策略. 以至于该策略成为浏览器最核心最基本的安全功能, 如果缺少了同源策略, web的安全将无从谈起.(这段文字是cv的)

这下好了,同源策略下的web世界, 域的壁垒高筑, 保证各个网页相互独立, 互相之间不能直接访问, iframe, ajax 均受其限制, 而script标签不受此限制.

注: 如非特别说明, 均指非CORS的, 普通跨域请求.

咳咳,我们讲json呢,扯远了,快回来

哎,哎,相公,别敲我脑袋瓜子啊,疼,敲笨了你就只能有个笨媳妇。人家这不是麻溜的回来了嘛,你倒是给我说说json和惊悚有啥不同。

“你知道啥是json么?”

“本大喵当然知道,json是一种数据格式”

“手写一段给本汪瞅瞅”

“算你上次没逃课,那你给我说说,这个json有啥要注意的地方?”

“咦,json不就简单的数据格式吗,有啥要注意?”

“就知道你上次没认真听,肯定开小差了,今晚回去小鱼干没了。”

“喵呜~~~人家错了,你再说一遍吧?嘤嘤嘤”

“记得下次考你,看仔细了”

■ ■■■■

这会儿带你认识认识jsonp了,看会儿惊悚片

“喵喵,你知道ajax么?”

“听过,但是不太了解”

“推荐一个blog,你去看看,下次讲给我听听,答的好有小鱼干吃哟”

“猴!得令”

Ajax直接请求普通文件存在跨域无权限访问的问题,无论是静态页面还是动态页面,web服务,WCF(喵呜,这是啥?),但是在web页面上调用js文件时不受到跨域的影响(凡是拥有src属性的都有跨域的神奇能力),所以可以通过在远程服务器上设法把数据装进js格式的文件里,供客户端调用和进一步处理,而处理这些数据的格式可以是json,而且json还被原生js支持,很完美了。

方案如下:

Web客户端通过与调用脚本一模一样的方式,来调用跨域服务器上动态生成的js格式文件,客户端在对json文件成功调用之后,获得了自己所需的数据,这就是jsonp,该协议的一个要点就是允许用户传递一个callback参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住json数据,这样客户端就可以随意定制函数来自动处理返回数据。

具体实现示例:

喵喵:远程服务器。cat.com

汪汪:本地服务器.dag.com

1 miaomiao.js是cat.com根目录下的一个js文件。 代码如下

alert(‘喵呜,我是喵喵’);

Jsonp.html是dag.com下的一个页面:

这里会弹出弹窗,现实跨域成功。

2 在jsonp.html页面定义一个函数。然后在远程文件miaomiao.js中传入数据进行调用。

miaomiao.js:

运行之后,显示本地调用成功,并且获取数据。但是如何让miaomiao知道它调用的dog函数叫什么呢?毕竟附近的dog太多了。

3 喵喵和汪汪想了一个办法,如果汪汪想要调用喵喵,就在返回的骨头上加一个标志,说我想调用XXX函数的js代码,你丫别给我传错了啊。于是喵喵就按照骨头上的需求来生成js脚本并且给汪汪一个响应“拿好你的骨头,别搞丢了” 汪汪的jsonp.html

上面实现的是编码动态查询,也是jsonp客户端实现的核心。

下面是如何完成jsonp调用的全过程。 上面url中的code参数表示dog告诉cat我要查询附近猪骨的信息,并且把一个叫callback的骨头给cat,说这是我们的暗号(boneHandler),别和其他狗子搞混了,你把结果都放到这块骨头的这个暗号中给我传过来。

于是这个叫做boneResult.aspx的页面生成了一段这样的代码提供给jsonp.html

4 如何用jquery实现? Attention:jquery在处理jsonp类型的ajax时(虽然jquery也把jsonp归入了ajax,但其实它们真的不是一回事儿),自动帮你生成回调函数并把数据取出来供success属性方法来调用

1、ajax和jsonp这两种技术在调用方式上“看起来”很像,目的也一样,都是请求一个url,然后把服务器返回的数据进行处理,因此jquery和ext(?)等框架都把jsonp作为ajax的一种形式进行了封装;

2、但ajax和jsonp其实本质上是不同的东西。ajax的核心是通过XmlHttpRequest获取非本页内容,而jsonp的核心则是动态添加标签来调用服务器提供的js脚本。

3、其实ajax与jsonp的区别不在于是否跨域,ajax通过服务端代理一样可以实现跨域,jsonp本身也不排斥同域的数据的获取。

4、还有就是,jsonp是一种方式或者说非强制性协议,如同ajax一样,它也不一定非要用json格式来传递数据,如果你愿意,字符串都行,只不过这样不利于用jsonp提供公开服务。

总而言之,jsonp不是ajax的一个特例,哪怕jquery等巨头把jsonp封装进了ajax,也不能改变着一点!

“傻喵,听懂了么?”

参考资料:

路易斯的blog(推荐看看他的blog,内容满赞的,尤其那个关于mac上使用alfred的技巧,很清晰)

阮一峰的日志

end

有肉吃

  • 发表于:
  • 原文链接:https://kuaibao.qq.com/s/20180820G010UF00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

同媒体快讯

扫码关注云+社区

领取腾讯云代金券