json & jsonp

image

对于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是一种数据格式”

“手写一段给本汪瞅瞅”

// 描述一个人

var person = {
    "Name": "大宝",
    "Age": 1,
    "Company": "IBM",
    "Engineer": true
}

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

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

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

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

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

image

image

image

image

image

image

image

image

■ ■■■■

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

“喵喵,你知道ajax么?”

“听过,但是不太了解”

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

“猴!得令”

image

    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文件。 代码如下

<pre style="margin: 0.5em 0px; padding: 0.4em 0.6em; border-radius: 8px; background: rgb(248, 248, 248); box-sizing: border-box;">alert(‘喵呜,我是喵喵’);</pre>

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

image

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

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

image

miaomiao.js:

localHandler({"result":"我是远程猫js带来的数据"});

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

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

image

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

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

    于是这个叫做boneResult.aspx的页面生成了一段这样的代码提供给jsonp.html
boneHandler({
    "code": "pig",
    "price": 170,
    "nums": 5
});

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

image

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

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

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

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

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

“傻喵,听懂了么?”

image

参考资料:

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

阮一峰的日志

我的博客即将搬运同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=1eteae3c4sdc0

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏葡萄城控件技术团队

Winform文件下载之WebClient

最近升级了公司内部使用的一个下载小工具,主要提升了下面几点: 1. 在一些分公司的局域网中,连接不上外网 2. 服务器上的文件更新后,下载到的还是更新前的文件 ...

21550
来自专栏BestSDK

Python开发必备的6个库,有了它事半功倍!

01 Python 必备之 PyPy PyPy 主要用于何处? 如果你需要更快的 Python 应用程序,最简单的实现的方法就是通过 PyPy ,Python ...

43480
来自专栏前端迷

ajax和fetch、axios的优缺点以及比较

前端是个发展迅速的领域,前端请求自然也发展迅速,从原生的XHR到jquery ajax,再到现在的axios和fetch。

3.7K20
来自专栏互联网杂技

如何学习用Typescript写Reactjs?

首先扫盲一下,先从搭建环境开始: 1.安装node,因为ts的编译器是js/ts写的; 安装node后同时获得npm命令,这是nodejs世界里的包管理器...

666120
来自专栏逸鹏说道

bootstrap + requireJS+ director+ knockout + web API = 一个时髦的单页程序

bootstrap + requireJS+ director+ knockout + web API = 一个时髦的单页程序 也许单页程序(Single Pa...

38550
来自专栏用户1191492的专栏

JClouds的命令行界面

我已经使用JCloud(一种面向Java支持多种云的工具集)一年了。到目前为止,我已经在很多领域广泛地使用了JCloud,特别是在Fuse Eco...

33190
来自专栏码匠的流水账

聊聊jdbc的大数据量读写相关异常的防御措施

jdbc提供fetchSize参数来设置每次查询按fetchSize分批获取。不同的数据库的jdbc driver实现不一样。

18210
来自专栏python学习之旅

Python网络爬虫笔记(五):下载、分析京东P20销售数据

1、      翻页的时候,谷歌F12的Network页签可以看到下面的请求。(这里的翻页指商品评价中1、2、3页等)

53070
来自专栏文大师的新世界

9. redux如何精简代码

通过之前的代码不难看出redux系统里的ActionType、Action、Reducer都有一定的共性,小项目无所谓,这样写更清晰,但是一旦组件以及业务增多,...

18650
来自专栏py+selenium

py+selenium遇见IE,元素只有name属性【神奇解决】

IE8的问题:IE8不支持getElementByName,而属性中又没有ID,定位难度较大。

42510

扫码关注云+社区

领取腾讯云代金券