一看就懂:jsonp详解


Posted in Javascript onJune 01, 2015

json相信大家都用的多,jsonp我就一直没有机会用到,但也经常看到,只知道是“用来跨域的”,一直不知道具体是个什么东西。今天总算搞明白了。下面一步步来搞清楚jsonp是个什么玩意。

同源策略

首先基于安全的原因,浏览器是存在同源策略这个机制的,同源策略阻止从一个源加载的文档或脚本获取或设置另一个源加载的文档的属性。看起来不知道什么意思,实践一下就知道了。

1、随便建两个网页

一个端口是2698,一个2701,按照定义它们是不同源的。

一看就懂:jsonp详解

2.用jQuery发起不同源的请求
在2698端口的网页上添加一个按钮,Click事件随便发起两个向端口为2701域的请求。

$("#getOtherDomainThings").click(function () {

    $.get("http://localhost:2701/Scripts/jquery-1.4.4.min.js", function (data) {

        console.log(data)

    })
    $.get("http://localhost:2701/home/index", function (data) {

        console.log(data)

    })

})

根据同源策略,很明显会悲剧了。浏览器会阻止,根本不会发起这个请求。(not allowed by Access-Control-Allow-Origin)

一看就懂:jsonp详解

OK,原来jsonp是要解决这个问题的。

script标签的跨域能力
不知道大家知不知道CDN这个东西,例如微软的CDN,使用它,我们的网页可以不提供jQuery,由微软的网站帮我们提供:

<script src="http://ajax.aspnetcdn.com/ajax/jquery/jquery-1.8.0.js" type="text/javascript"></script>

回到我们的2698端口的网页,上面我们在Click事件里有一个对2701端口域的jQuery文件的请求,这次使用script标签来请求。
<script type="text/javascript" src="http://localhost:2701/Scripts/jquery-1.4.4.min.js"></script>

当然,200,OK了

一看就懂:jsonp详解

同样是端口2698的网页发起对2701域的请求,放在script里设置scr属性的OK了,另一个方式就悲剧。利用script的跨域能力,这就是jsonp的基础。

利用script获取不同源的json
既然它叫jsonp,很明显目的还是json,而且是跨域获取。根据上面的分析,很容易想到:利用js构造一个script标签,把json的url赋给script的scr属性,把这个script插入到dom里,让浏览器去获取。实践:

function CreateScript(src) {

    $("<script><//script>").attr("src", src).appendTo("body")

}

添加一个按钮事件来测试一下:
$("#getOtherDomainJson").click(function () {

    $.get('http://localhost:2701/home/somejson', function (data) {

        console.log(data)

    })

})

一看就懂:jsonp详解

首先,第一个浏览器,http://localhost:2701/home/somejson这个Url的确是存在一个json的,而且在 2698网页上用script标签来请求这个2701这个Url也是200OK的,但是最下面报js语法错误了。原来用script标签加载完后,会立即 把响应当js去执行,很明显{"Email":"zhww@outlook.com","Remark":"我来自遥远的东方"}不是合法的js语句。

利用script获取异域的jsonp

显然,把上面的json放到一个回调方法里是最简单的方法。例如,变成这样:

一看就懂:jsonp详解

如果存在jsonpcallback这个方法,那么jsonpcallback({"Email":"zhww@outlook.com","Remark":"我来自遥远的东方"})就是合法的js语句。

由于服务器不知道客户端的回调是什么,不可能hard code成jsonpcallback,所以就带一个QueryString让客户端告诉服务端,回调方法是什么,当然,QueryString的key要遵从服务端的约定,上面的是”callback“。

添加回调函数:

function jsonpcallback(json) {

    console.log(json)

}

把前面的方法稍微改改参数:
$("#getJsonpByHand").click(function () {

    CreateScript("http://localhost:2701/home/somejsonp?callback=jsonpcallback")

})

一看就懂:jsonp详解

200OK,服务器返回jsonpcallback({"Email":"zhww@outlook.com","Remark":"我来自遥远的 东方"}),我们也写了jsonpcallback方法,当然会执行。OK顺利获得了json。没错,到这里就是jsonp的全部。

利用jQuery获取jsonp
上面的方式中,又要插入script标签,又要定义一个回调,略显麻烦,利用jQuery可以直接得到想要的json数据,同样是上面的jsonp:

$("#getJsonpByJquery").click(function () {

    $.ajax({

        url: 'http://localhost:2701/home/somejsonp',

        dataType: "jsonp",

        jsonp: "callback",

        success: function (data) {

            console.log(data)

        }

    })

})

得到的结果跟上面类似。

总结

一句话就是利用script标签绕过同源策略,获得一个类似这样的数据,jsonpcallback是页面存在的回调方法,参数就是想得到的json。

jsonpcallback({"Email":"zhww@outlook.com","Remark":"我来自遥远的东方"})

ADD 原生js:

<button id="btn">click</button>

<script type="text/javascript">

    function $(str){

        return document.getElementById(str)

    }

    function CreateScript(src) {

        var Scrip=document.createElement('script');

        Scrip.src=src;

        document.body.appendChild(Scrip);

    }

    function jsonpcallback(json) {

            console.log(json);//Object { email="中国", email2="中国222"}

    }

    $('btn').onclick=function(){

      CreateScript("http://localhost:51335/somejson?callback=jsonpcallback")    

    }

</script>
Javascript 相关文章推荐
使用js写的一个简易的投票
Nov 27 Javascript
js动态改变select选择变更option的index值示例
Jul 10 Javascript
JS实现的文字与图片定时切换效果代码
Oct 06 Javascript
js 右侧浮动层效果实现代码(跟随滚动)
Nov 22 Javascript
Javascript 调用 ActionScript 的简单方法
Sep 22 Javascript
js实现5秒倒计时重新发送短信功能
Feb 05 Javascript
Angular4.x通过路由守卫进行路由重定向实现根据条件跳转到相应的页面(推荐)
May 10 Javascript
JS实现动态生成html table表格的方法分析
Jul 11 Javascript
vue中使用cookies和crypto-js实现记住密码和加密的方法
Oct 18 Javascript
详解vue挂载到dom上会发生什么
Jan 20 Javascript
vue实现购物车抛物线小球动画效果的方法详解
Feb 13 Javascript
vue 实现setInterval 创建和销毁实例
Jul 21 Javascript
JS数组array元素的添加和删除方法代码实例
Jun 01 #Javascript
JQuery判断checkbox是否选中及其它复选框操作方法合集
Jun 01 #Javascript
window.onload与$(document).ready()的区别分析
May 30 #Javascript
JQuery给网页更换皮肤的方法
May 30 #Javascript
jQuery实现给页面换肤的方法
May 30 #Javascript
js获取滚动距离的方法
May 30 #Javascript
jquery简单实现外部链接用新窗口打开的方法
May 30 #Javascript
You might like
php利用cookie实现访问次数统计代码
2011/05/19 PHP
ThinkPHP项目分组配置方法分析
2016/03/23 PHP
Yii2框架实现利用mpdf创建pdf文件功能示例
2019/02/08 PHP
PHP多进程通信-消息队列使用
2019/03/08 PHP
TP5框架model常见操作示例小结【增删改查、聚合、时间戳、软删除等】
2020/04/05 PHP
在Iframe中获取父窗口中表单的值(示例代码)
2013/11/22 Javascript
JavaScript执行顺序详细介绍
2013/12/04 Javascript
node.js中的events.emitter.once方法使用说明
2014/12/10 Javascript
Javascript实现可旋转的圆圈实例代码
2015/08/04 Javascript
JQuery移动页面开发之屏幕方向改变与滚屏的实现
2015/12/03 Javascript
浅析javascript异步执行函数导致的变量变化问题解决思路
2016/05/13 Javascript
js内置对象处理_打印学生成绩单的简单实现
2016/09/24 Javascript
Vue.js框架路由使用方法实例详解
2017/08/25 Javascript
Redux 和 Mobx的选择问题:让你不再困惑!
2017/09/18 Javascript
解析Vue 2.5的Diff算法
2017/11/28 Javascript
老生常谈JS中的继承及实现代码
2018/07/06 Javascript
node错误处理与日志记录的实现
2018/12/24 Javascript
[17:45]DOTA2 HEROES教学视频教你分分钟做大人-军团指挥官
2014/06/11 DOTA
[01:01:25]DOTA2上海特级锦标赛B组资格赛#2 Fnatic VS Spirit第三局
2016/02/27 DOTA
[51:17]完美世界DOTA2联赛循环赛Inki vs DeMonsTer 第二场 10月30日
2020/10/31 DOTA
2款Python内存检测工具介绍和使用方法
2014/06/01 Python
Pycharm编辑器技巧之自动导入模块详解
2017/07/18 Python
Python3中的列表,元组,字典,字符串相关知识小结
2017/11/10 Python
python读取文本中的坐标方法
2018/10/14 Python
python输出电脑上所有的串口名的方法
2019/07/02 Python
PyCharm Anaconda配置PyQt5开发环境及创建项目的教程详解
2020/03/24 Python
解决Keras中循环使用K.ctc_decode内存不释放的问题
2020/06/29 Python
StubHub澳大利亚:购买或出售您的门票
2019/08/01 全球购物
Lentiamo比利时:便宜的隐形眼镜
2020/02/14 全球购物
房地产销售计划书
2014/01/10 职场文书
2014年党支部学习材料
2014/05/19 职场文书
鼓舞士气的口号
2014/06/16 职场文书
2014年依法行政工作总结
2014/11/19 职场文书
2015年学校团委工作总结
2015/05/26 职场文书
小学四年级班主任工作经验交流材料
2015/11/02 职场文书
table不让td文字溢出操作方法
2022/12/24 HTML / CSS